Cleanup: remove intermediate menu drawing function
[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 from bpy.app.translations import pgettext_iface as iface_
24 from bl_operators.presets import PresetMenu
25 from .properties_grease_pencil_common import (
26     AnnotationDrawingToolsPanel,
27     AnnotationDataPanel,
28 )
29
30
31 class CLIP_UL_tracking_objects(UIList):
32     def draw_item(self, context, layout, data, item, icon,
33                   active_data, active_propname, index):
34         # assert(isinstance(item, bpy.types.MovieTrackingObject)
35         tobj = item
36         if self.layout_type in {'DEFAULT', 'COMPACT'}:
37             layout.prop(tobj, "name", text="", emboss=False,
38                         icon='CAMERA_DATA' if tobj.is_camera
39                         else 'OBJECT_DATA')
40         elif self.layout_type == 'GRID':
41             layout.alignment = 'CENTER'
42             layout.label(text="",
43                          icon='CAMERA_DATA' if tobj.is_camera
44                          else 'OBJECT_DATA')
45
46
47 class CLIP_PT_display(Panel):
48     bl_space_type = 'CLIP_EDITOR'
49     bl_region_type = 'HEADER'
50     bl_label = "Clip Display"
51     bl_ui_units_x = 13
52
53     def draw(self, context):
54         pass
55
56
57 class CLIP_PT_marker_display(Panel):
58     bl_space_type = 'CLIP_EDITOR'
59     bl_region_type = 'HEADER'
60     bl_label = "Marker Display"
61     bl_parent_id = 'CLIP_PT_display'
62     bl_ui_units_x = 13
63
64     def draw(self, context):
65         layout = self.layout
66
67         view = context.space_data
68
69         row = layout.row()
70
71         col = row.column()
72         col.prop(view, "show_marker_pattern", text="Pattern")
73         col.prop(view, "show_marker_search", text="Search")
74
75         col.active = view.show_track_path
76         col.prop(view, "show_track_path", text="Path")
77         col.prop(view, "path_length", text="Length")
78
79         col = row.column()
80         col.prop(view, "show_disabled", text="Show Disabled")
81         col.prop(view, "show_names", text="Info")
82
83         if view.mode != 'MASK':
84             col.prop(view, "show_bundles", text="3D Markers")
85         col.prop(view, "show_tiny_markers", text="Draw Thin")
86
87
88 class CLIP_PT_clip_display(Panel):
89     bl_space_type = 'CLIP_EDITOR'
90     bl_region_type = 'HEADER'
91     bl_label = "Clip Display"
92     bl_parent_id = 'CLIP_PT_display'
93     bl_ui_units_x = 13
94
95     def draw(self, context):
96         layout = self.layout
97
98         sc = context.space_data
99
100         col = layout.column(align=True)
101
102         row = layout.row(align=True)
103         row.prop(sc, "show_red_channel", text="R", toggle=True)
104         row.prop(sc, "show_green_channel", text="G", toggle=True)
105         row.prop(sc, "show_blue_channel", text="B", toggle=True)
106         row.separator()
107         row.prop(sc, "use_grayscale_preview", text="B/W", toggle=True)
108         row.separator()
109         row.prop(sc, "use_mute_footage", text="", icon='VISIBLE_IPO_ON', toggle=True)
110
111         layout.separator()
112
113         row = layout.row()
114         col = row.column()
115         col.prop(sc.clip_user, "use_render_undistorted", text="Render Undistorted")
116         col.prop(sc, "lock_selection", text="Lock to Selection")
117         col = row.column()
118         col.prop(sc, "show_stable", text="Show Stable")
119         col.prop(sc, "show_grid", text="Grid")
120         col.prop(sc, "use_manual_calibration", text="Calibration")
121
122         clip = sc.clip
123         if clip:
124             col = layout.column()
125             col.prop(clip, "display_aspect", text="Display Aspect Ratio")
126
127
128 class CLIP_HT_header(Header):
129     bl_space_type = 'CLIP_EDITOR'
130
131     def _draw_tracking(self, context):
132         layout = self.layout
133
134         sc = context.space_data
135         clip = sc.clip
136
137         CLIP_MT_tracking_editor_menus.draw_collapsible(context, layout)
138
139         layout.separator_spacer()
140
141         row = layout.row()
142         if sc.view == 'CLIP':
143             row.template_ID(sc, "clip", open="clip.open")
144         else:
145             row = layout.row(align=True)
146             props = row.operator("clip.refine_markers", text="", icon='TRACKING_REFINE_BACKWARDS')
147             props.backwards = True
148             row.separator()
149
150             props = row.operator("clip.clear_track_path", text="", icon='TRACKING_CLEAR_BACKWARDS')
151             props.action = 'UPTO'
152             row.separator()
153
154             props = row.operator("clip.track_markers", text="", icon='TRACKING_BACKWARDS_SINGLE')
155             props.backwards = True
156             props.sequence = False
157             props = row.operator("clip.track_markers", text="",
158                                  icon='TRACKING_BACKWARDS')
159             props.backwards = True
160             props.sequence = True
161             props = row.operator("clip.track_markers", text="", icon='TRACKING_FORWARDS')
162             props.backwards = False
163             props.sequence = True
164             props = row.operator("clip.track_markers", text="", icon='TRACKING_FORWARDS_SINGLE')
165             props.backwards = False
166             props.sequence = False
167             row.separator()
168
169             props = row.operator("clip.clear_track_path", text="", icon='TRACKING_CLEAR_FORWARDS')
170             props.action = 'REMAINED'
171             row.separator()
172
173             props = row.operator("clip.refine_markers", text="", icon='TRACKING_REFINE_FORWARDS')
174             props.backwards = False
175
176         layout.separator_spacer()
177
178         if clip:
179             tracking = clip.tracking
180             active_object = tracking.objects.active
181
182             if sc.view == 'CLIP':
183                 layout.template_running_jobs()
184
185                 r = active_object.reconstruction
186
187                 if r.is_valid and sc.view == 'CLIP':
188                     layout.label(text="Solve error: %.4f" %
189                                  (r.average_error))
190
191                 row = layout.row()
192                 row.prop(sc, "pivot_point", text="", icon_only=True)
193                 row = layout.row(align=True)
194                 icon = 'LOCKED' if sc.lock_selection else 'UNLOCKED'
195                 row.prop(sc, "lock_selection", icon=icon, text="")
196                 row.popover(panel='CLIP_PT_display')
197
198             elif sc.view == 'GRAPH':
199                 row = layout.row(align=True)
200                 row.prop(sc, "show_graph_only_selected", text="")
201                 row.prop(sc, "show_graph_hidden", text="")
202
203                 row = layout.row(align=True)
204
205                 if sc.show_filters:
206                     row.prop(sc, "show_filters", icon='DISCLOSURE_TRI_DOWN',
207                              text="Filters")
208
209                     sub = row.row(align=True)
210                     sub.active = clip.tracking.reconstruction.is_valid
211                     sub.prop(sc, "show_graph_frames", icon='SEQUENCE', text="")
212
213                     row.prop(sc, "show_graph_tracks_motion", icon='GRAPH', text="")
214                     row.prop(sc, "show_graph_tracks_error", icon='ANIM', text="")
215                 else:
216                     row.prop(sc, "show_filters", icon='DISCLOSURE_TRI_RIGHT',
217                              text="Filters")
218
219             elif sc.view == 'DOPESHEET':
220                 dopesheet = tracking.dopesheet
221
222                 row = layout.row(align=True)
223                 row.prop(dopesheet, "show_only_selected", text="")
224                 row.prop(dopesheet, "show_hidden", text="")
225
226                 row = layout.row(align=True)
227                 row.prop(dopesheet, "sort_method", text="")
228                 row.prop(dopesheet, "use_invert_sort",
229                          text="Invert", toggle=True)
230
231     def _draw_masking(self, context):
232         layout = self.layout
233
234         tool_settings = context.tool_settings
235         sc = context.space_data
236         clip = sc.clip
237
238         CLIP_MT_masking_editor_menus.draw_collapsible(context, layout)
239
240         layout.separator_spacer()
241
242         row = layout.row()
243         row.template_ID(sc, "clip", open="clip.open")
244
245         layout.separator_spacer()
246
247         if clip:
248
249             layout.prop(sc, "pivot_point", text="", icon_only=True)
250
251             row = layout.row(align=True)
252             row.prop(tool_settings, "use_proportional_edit_mask", text="", icon_only=True)
253             sub = row.row(align=True)
254             sub.active = tool_settings.use_proportional_edit_mask
255             sub.prop(tool_settings, "proportional_edit_falloff", text="", icon_only=True)
256
257             row = layout.row()
258             row.template_ID(sc, "mask", new="mask.new")
259             row.popover(panel='CLIP_PT_mask_display')
260             row = layout.row(align=True)
261             icon = 'LOCKED' if sc.lock_selection else 'UNLOCKED'
262             row.prop(sc, "lock_selection", icon=icon, text="")
263             row.popover(panel='CLIP_PT_display')
264
265     def draw(self, context):
266         layout = self.layout
267
268         sc = context.space_data
269
270         row = layout.row(align=True)
271         row.template_header()
272
273         layout.prop(sc, "mode", text="")
274         if sc.mode == 'TRACKING':
275             layout.prop(sc, "view", text="")
276             self._draw_tracking(context)
277         else:
278             self._draw_masking(context)
279
280
281 class CLIP_MT_tracking_editor_menus(Menu):
282     bl_idname = "CLIP_MT_tracking_editor_menus"
283     bl_label = ""
284
285     def draw(self, context):
286         layout = self.layout
287         sc = context.space_data
288         clip = sc.clip
289
290         layout.menu("CLIP_MT_view")
291
292         if sc.view == 'CLIP':
293             if clip:
294                 layout.menu("CLIP_MT_select")
295                 layout.menu("CLIP_MT_clip")
296                 layout.menu("CLIP_MT_track")
297                 layout.menu("CLIP_MT_reconstruction")
298             else:
299                 layout.menu("CLIP_MT_clip")
300
301
302 class CLIP_MT_masking_editor_menus(Menu):
303
304     bl_idname = "CLIP_MT_masking_editor_menus"
305     bl_label = ""
306
307     def draw(self, context):
308         layout = self.layout
309         sc = context.space_data
310         clip = sc.clip
311
312         layout.menu("CLIP_MT_view")
313
314         if clip:
315             layout.menu("MASK_MT_select")
316             layout.menu("CLIP_MT_clip")  # XXX - remove?
317             layout.menu("MASK_MT_add")
318             layout.menu("MASK_MT_mask")
319         else:
320             layout.menu("CLIP_MT_clip")  # XXX - remove?
321
322
323 class CLIP_PT_clip_view_panel:
324
325     @classmethod
326     def poll(cls, context):
327         sc = context.space_data
328         clip = sc.clip
329
330         return clip and sc.view == 'CLIP'
331
332
333 class CLIP_PT_tracking_panel:
334
335     @classmethod
336     def poll(cls, context):
337         sc = context.space_data
338         clip = sc.clip
339
340         return clip and sc.mode == 'TRACKING' and sc.view == 'CLIP'
341
342
343 class CLIP_PT_reconstruction_panel:
344
345     @classmethod
346     def poll(cls, context):
347         sc = context.space_data
348         clip = sc.clip
349
350         return clip and sc.view == 'CLIP'
351
352
353 class CLIP_PT_tools_clip(Panel):
354     bl_space_type = 'CLIP_EDITOR'
355     bl_region_type = 'TOOLS'
356     bl_label = "Clip"
357     bl_translation_context = bpy.app.translations.contexts.id_movieclip
358     bl_category = "Track"
359
360     @classmethod
361     def poll(cls, context):
362         sc = context.space_data
363         clip = sc.clip
364
365         return clip and sc.view == 'CLIP' and sc.mode != 'MASK'
366
367     def draw(self, context):
368         layout = self.layout
369
370         col = layout.column(align=True)
371         col.operator("clip.set_scene_frames")
372         row = col.row(align=True)
373         row.operator("clip.prefetch", text="Prefetch")
374         row.operator("clip.reload", text="Reload")
375
376
377 class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel):
378     bl_space_type = 'CLIP_EDITOR'
379     bl_region_type = 'TOOLS'
380     bl_label = "Marker"
381     bl_category = "Track"
382
383     def draw(self, context):
384         layout = self.layout
385
386         sc = context.space_data
387
388         col = layout.column(align=True)
389         row = col.row(align=True)
390         row.operator("clip.add_marker_at_click", text="Add")
391         row.operator("clip.delete_track", text="Delete")
392         col.operator("clip.detect_features")
393
394
395 class CLIP_PT_tracking_settings(CLIP_PT_tracking_panel, Panel):
396     bl_space_type = 'CLIP_EDITOR'
397     bl_region_type = 'TOOLS'
398     bl_label = "Tracking Settings"
399     bl_category = "Track"
400
401     def draw_header_preset(self, context):
402         CLIP_PT_tracking_settings_presets.draw_panel_header(self.layout)
403
404     def draw(self, context):
405         layout = self.layout
406         layout.use_property_split = True
407         layout.use_property_decorate = False
408
409         sc = context.space_data
410         clip = sc.clip
411         settings = clip.tracking.settings
412
413         col = layout.column(align=True)
414         col.prop(settings, "default_pattern_size")
415         col.prop(settings, "default_search_size")
416
417         col.separator()
418
419         col.prop(settings, "default_motion_model")
420         col.prop(settings, "default_pattern_match", text="Match")
421
422         col.prop(settings, "use_default_brute")
423         col.prop(settings, "use_default_normalization")
424
425         col = layout.column()
426
427         row = col.row(align=True)
428         row.use_property_split = False
429         row.prop(settings, "use_default_red_channel",
430                  text="R", toggle=True)
431         row.prop(settings, "use_default_green_channel",
432                  text="G", toggle=True)
433         row.prop(settings, "use_default_blue_channel",
434                  text="B", toggle=True)
435
436         col.separator()
437         col.operator("clip.track_settings_as_default",
438                      text="Copy From Active Track")
439
440
441 class CLIP_PT_tracking_settings_extras(CLIP_PT_tracking_panel, Panel):
442     bl_label = "Tracking Settings Extra"
443     bl_parent_id = "CLIP_PT_tracking_settings"
444     bl_space_type = 'CLIP_EDITOR'
445     bl_region_type = 'TOOLS'
446     bl_options = {'DEFAULT_CLOSED'}
447
448     def draw(self, context):
449         layout = self.layout
450         layout.use_property_split = True
451         layout.use_property_decorate = False
452
453         sc = context.space_data
454         clip = sc.clip
455         settings = clip.tracking.settings
456
457         col = layout.column()
458         col.prop(settings, "default_weight")
459         col = layout.column(align=True)
460         col.prop(settings, "default_correlation_min")
461         col.prop(settings, "default_margin")
462         col.prop(settings, "use_default_mask")
463
464
465 class CLIP_PT_tools_tracking(CLIP_PT_tracking_panel, Panel):
466     bl_space_type = 'CLIP_EDITOR'
467     bl_region_type = 'TOOLS'
468     bl_label = "Track"
469     bl_category = "Track"
470     bl_options = {'DEFAULT_CLOSED'}
471
472     def draw(self, context):
473         layout = self.layout
474
475         row = layout.row(align=True)
476         row.label(text="Track:")
477
478         props = row.operator("clip.track_markers", text="", icon='FRAME_PREV')
479         props.backwards = True
480         props.sequence = False
481         props = row.operator("clip.track_markers", text="",
482                              icon='PLAY_REVERSE')
483         props.backwards = True
484         props.sequence = True
485         props = row.operator("clip.track_markers", text="", icon='PLAY')
486         props.backwards = False
487         props.sequence = True
488         props = row.operator("clip.track_markers", text="", icon='FRAME_NEXT')
489         props.backwards = False
490         props.sequence = False
491
492         col = layout.column(align=True)
493         row = col.row(align=True)
494         row.label(text="Clear:")
495         row.scale_x = 2.0
496
497         props = row.operator("clip.clear_track_path", text="", icon='BACK')
498         props.action = 'UPTO'
499
500         props = row.operator("clip.clear_track_path", text="", icon='FORWARD')
501         props.action = 'REMAINED'
502
503         col = layout.column()
504         row = col.row(align=True)
505         row.label(text="Refine:")
506         row.scale_x = 2.0
507
508         props = row.operator("clip.refine_markers", text="", icon='LOOP_BACK')
509         props.backwards = True
510
511         props = row.operator("clip.refine_markers", text="", icon='LOOP_FORWARDS')
512         props.backwards = False
513
514         col = layout.column(align=True)
515         row = col.row(align=True)
516         row.label(text="Merge:")
517         row.operator("clip.join_tracks", text="Join Tracks")
518
519
520 class CLIP_PT_tools_plane_tracking(CLIP_PT_tracking_panel, Panel):
521     bl_space_type = 'CLIP_EDITOR'
522     bl_region_type = 'TOOLS'
523     bl_label = "Plane Track"
524     bl_options = {'DEFAULT_CLOSED'}
525     bl_category = "Solve"
526
527     def draw(self, context):
528         layout = self.layout
529         layout.operator("clip.create_plane_track")
530
531
532 class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel):
533     bl_space_type = 'CLIP_EDITOR'
534     bl_region_type = 'TOOLS'
535     bl_label = "Solve"
536     bl_category = "Solve"
537
538     def draw(self, context):
539         layout = self.layout
540         layout.use_property_split = True
541         layout.use_property_decorate = False
542
543         clip = context.space_data.clip
544         tracking = clip.tracking
545         settings = tracking.settings
546         tracking_object = tracking.objects.active
547
548         col = layout.column()
549         col.prop(settings, "use_tripod_solver", text="Tripod")
550         col = layout.column()
551         col.active = not settings.use_tripod_solver
552         col.prop(settings, "use_keyframe_selection", text="Keyframe")
553
554         col = layout.column(align=True)
555         col.active = (not settings.use_tripod_solver and
556                       not settings.use_keyframe_selection)
557         col.prop(tracking_object, "keyframe_a")
558         col.prop(tracking_object, "keyframe_b")
559
560         col = layout.column()
561         col.active = tracking_object.is_camera
562         col.prop(settings, "refine_intrinsics", text="Refine")
563
564         col = layout.column(align=True)
565         col.scale_y = 2.0
566
567         col.operator("clip.solve_camera",
568                      text="Solve Camera Motion" if tracking_object.is_camera
569                      else "Solve Object Motion")
570
571
572 class CLIP_PT_tools_cleanup(CLIP_PT_tracking_panel, Panel):
573     bl_space_type = 'CLIP_EDITOR'
574     bl_region_type = 'TOOLS'
575     bl_label = "Clean up"
576     bl_options = {'DEFAULT_CLOSED'}
577     bl_category = "Solve"
578
579     def draw(self, context):
580         layout = self.layout
581         layout.use_property_split = True
582         layout.use_property_decorate = False
583
584         clip = context.space_data.clip
585         settings = clip.tracking.settings
586
587         col = layout.column()
588         col.prop(settings, "clean_frames", text="Frames")
589         col.prop(settings, "clean_error", text="Error")
590         col.prop(settings, "clean_action", text="Type")
591         col.separator()
592         col.operator("clip.clean_tracks")
593         col.operator("clip.filter_tracks")
594
595
596 class CLIP_PT_tools_geometry(CLIP_PT_tracking_panel, Panel):
597     bl_space_type = 'CLIP_EDITOR'
598     bl_region_type = 'TOOLS'
599     bl_label = "Geometry"
600     bl_options = {'DEFAULT_CLOSED'}
601     bl_category = "Solve"
602
603     def draw(self, context):
604         layout = self.layout
605
606         layout.operator("clip.bundles_to_mesh")
607         layout.operator("clip.track_to_empty")
608
609
610 class CLIP_PT_tools_orientation(CLIP_PT_tracking_panel, Panel):
611     bl_space_type = 'CLIP_EDITOR'
612     bl_region_type = 'TOOLS'
613     bl_label = "Orientation"
614     bl_category = "Solve"
615
616     def draw(self, context):
617         layout = self.layout
618         layout.use_property_split = True
619         layout.use_property_decorate = False
620
621         sc = context.space_data
622         settings = sc.clip.tracking.settings
623
624         col = layout.column(align=True)
625
626         row = col.row(align=True)
627         row.operator("clip.set_plane", text="Floor").plane = 'FLOOR'
628         row.operator("clip.set_plane", text="Wall").plane = 'WALL'
629
630         col.operator("clip.set_origin")
631
632         row = col.row(align=True)
633         row.operator("clip.set_axis", text="Set X Axis").axis = 'X'
634         row.operator("clip.set_axis", text="Set Y Axis").axis = 'Y'
635
636         layout.separator()
637
638         col = layout.column()
639
640         row = col.row(align=True)
641         row.operator("clip.set_scale")
642         row.operator("clip.apply_solution_scale", text="Apply Scale")
643
644         col.prop(settings, "distance")
645
646
647 class CLIP_PT_tools_object(CLIP_PT_reconstruction_panel, Panel):
648     bl_space_type = 'CLIP_EDITOR'
649     bl_region_type = 'TOOLS'
650     bl_label = "Object"
651     bl_category = "Solve"
652
653     @classmethod
654     def poll(cls, context):
655         sc = context.space_data
656         if CLIP_PT_reconstruction_panel.poll(context) and sc.mode == 'TRACKING':
657             clip = sc.clip
658
659             tracking_object = clip.tracking.objects.active
660
661             return not tracking_object.is_camera
662
663         return False
664
665     def draw(self, context):
666         layout = self.layout
667
668         sc = context.space_data
669         clip = sc.clip
670         tracking_object = clip.tracking.objects.active
671         settings = sc.clip.tracking.settings
672
673         col = layout.column()
674
675         col.prop(tracking_object, "scale")
676
677         col.separator()
678
679         col.operator("clip.set_solution_scale", text="Set Scale")
680         col.prop(settings, "object_distance")
681
682
683 class CLIP_PT_objects(CLIP_PT_clip_view_panel, Panel):
684     bl_space_type = 'CLIP_EDITOR'
685     bl_region_type = 'UI'
686     bl_category = "Track"
687     bl_label = "Objects"
688     bl_options = {'DEFAULT_CLOSED'}
689
690     def draw(self, context):
691         layout = self.layout
692
693         sc = context.space_data
694         tracking = sc.clip.tracking
695
696         row = layout.row()
697         row.template_list("CLIP_UL_tracking_objects", "", tracking, "objects",
698                           tracking, "active_object_index", rows=1)
699
700         sub = row.column(align=True)
701
702         sub.operator("clip.tracking_object_new", icon='ADD', text="")
703         sub.operator("clip.tracking_object_remove", icon='REMOVE', text="")
704
705
706 class CLIP_PT_track(CLIP_PT_tracking_panel, Panel):
707     bl_space_type = 'CLIP_EDITOR'
708     bl_region_type = 'UI'
709     bl_category = "Track"
710     bl_label = "Track"
711
712     def draw(self, context):
713         layout = self.layout
714
715         sc = context.space_data
716         clip = context.space_data.clip
717         act_track = clip.tracking.tracks.active
718
719         if not act_track:
720             layout.active = False
721             layout.label(text="No active track")
722             return
723
724         row = layout.row()
725         row.prop(act_track, "name", text="")
726
727         sub = row.row(align=True)
728
729         sub.template_marker(sc, "clip", sc.clip_user, act_track, compact=True)
730
731         icon = 'LOCKED' if act_track.lock else 'UNLOCKED'
732         sub.prop(act_track, "lock", text="", icon=icon)
733
734         layout.template_track(sc, "scopes")
735
736         row = layout.row(align=True)
737         sub = row.row(align=True)
738         sub.prop(act_track, "use_red_channel", text="R", toggle=True)
739         sub.prop(act_track, "use_green_channel", text="G", toggle=True)
740         sub.prop(act_track, "use_blue_channel", text="B", toggle=True)
741
742         row.separator()
743
744         layout.use_property_split = True
745
746         row.prop(act_track, "use_grayscale_preview", text="B/W", toggle=True)
747
748         row.separator()
749         row.prop(act_track, "use_alpha_preview",
750                  text="", toggle=True, icon='IMAGE_ALPHA')
751
752         layout.prop(act_track, "weight")
753         layout.prop(act_track, "weight_stab")
754
755         if act_track.has_bundle:
756             label_text = "Average Error: %.4f" % (act_track.average_error)
757             layout.label(text=label_text)
758
759         layout.use_property_split = False
760
761         row = layout.row(align=True)
762         row.prop(act_track, "use_custom_color", text="")
763         CLIP_PT_track_color_presets.draw_menu(row, 'Custom Color Presets')
764         row.operator("clip.track_copy_color", icon='COPY_ID', text="")
765
766         if act_track.use_custom_color:
767             row = layout.row()
768             row.prop(act_track, "color", text="")
769
770
771 class CLIP_PT_plane_track(CLIP_PT_tracking_panel, Panel):
772     bl_space_type = 'CLIP_EDITOR'
773     bl_region_type = 'UI'
774     bl_category = "Track"
775     bl_label = "Plane Track"
776     bl_options = {'DEFAULT_CLOSED'}
777
778     def draw(self, context):
779         layout = self.layout
780         layout.use_property_split = True
781
782         clip = context.space_data.clip
783         active_track = clip.tracking.plane_tracks.active
784
785         if not active_track:
786             layout.active = False
787             layout.label(text="No active plane track")
788             return
789
790         layout.prop(active_track, "name")
791         layout.prop(active_track, "use_auto_keying")
792         layout.prop(active_track, "image")
793
794         row = layout.row()
795         row.active = active_track.image is not None
796         row.prop(active_track, "image_opacity", text="Opacity")
797
798
799 class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel):
800     bl_space_type = 'CLIP_EDITOR'
801     bl_region_type = 'UI'
802     bl_category = "Track"
803     bl_label = "Tracking Settings"
804     bl_options = {'DEFAULT_CLOSED'}
805
806     def draw(self, context):
807         layout = self.layout
808         layout.use_property_split = True
809         layout.use_property_decorate = False
810
811         clip = context.space_data.clip
812
813         col = layout.column()
814
815         active = clip.tracking.tracks.active
816         if active:
817             col.prop(active, "motion_model")
818             col.prop(active, "pattern_match", text="Match")
819
820             col.prop(active, "use_brute")
821             col.prop(active, "use_normalization")
822
823
824 class CLIP_PT_track_settings_extras(CLIP_PT_tracking_panel, Panel):
825     bl_space_type = 'CLIP_EDITOR'
826     bl_region_type = 'UI'
827     bl_category = "Track"
828     bl_label = "Tracking Settings Extras"
829     bl_parent_id = 'CLIP_PT_track_settings'
830     bl_options = {'DEFAULT_CLOSED'}
831
832     def draw(self, context):
833         layout = self.layout
834         layout.use_property_split = True
835         layout.use_property_decorate = False
836
837         clip = context.space_data.clip
838         active = clip.tracking.tracks.active
839         settings = clip.tracking.settings
840
841         col = layout.column(align=True)
842         col.prop(active, "correlation_min")
843         col.prop(active, "margin")
844
845         col = layout.column()
846         col.prop(active, "use_mask")
847         col.prop(active, "frames_limit")
848         col.prop(settings, "speed")
849
850
851 class CLIP_PT_tracking_camera(Panel):
852     bl_space_type = 'CLIP_EDITOR'
853     bl_region_type = 'UI'
854     bl_category = "Track"
855     bl_label = "Camera"
856     bl_options = {'DEFAULT_CLOSED'}
857
858     @classmethod
859     def poll(cls, context):
860         if CLIP_PT_clip_view_panel.poll(context):
861             sc = context.space_data
862
863             return sc.mode == 'TRACKING' and sc.clip
864
865         return False
866
867     def draw_header_preset(self, context):
868         CLIP_PT_camera_presets.draw_panel_header(self.layout)
869
870     def draw(self, context):
871         layout = self.layout
872         layout.use_property_split = True
873         layout.use_property_decorate = False
874
875         sc = context.space_data
876         clip = sc.clip
877
878         col = layout.column(align=True)
879         col.prop(clip.tracking.camera, "sensor_width", text="Sensor Width")
880         col.prop(clip.tracking.camera, "pixel_aspect", text="Pixel Aspect")
881
882         col = layout.column()
883         col.prop(clip.tracking.camera, "principal", text="Optical Center")
884         col.operator("clip.set_center_principal", text="Set Center")
885
886
887 class CLIP_PT_tracking_lens(Panel):
888     bl_space_type = 'CLIP_EDITOR'
889     bl_region_type = 'UI'
890     bl_category = "Track"
891     bl_label = "Lens"
892     bl_options = {'DEFAULT_CLOSED'}
893
894     @classmethod
895     def poll(cls, context):
896         if CLIP_PT_clip_view_panel.poll(context):
897             sc = context.space_data
898
899             return sc.mode == 'TRACKING' and sc.clip
900
901         return False
902
903     def draw(self, context):
904         layout = self.layout
905         layout.use_property_split = True
906         layout.use_property_decorate = False
907
908         sc = context.space_data
909         clip = sc.clip
910         camera = clip.tracking.camera
911
912         col = layout.column()
913
914         if camera.units == 'MILLIMETERS':
915             col.prop(camera, "focal_length")
916         else:
917             col.prop(camera, "focal_length_pixels")
918         col.prop(camera, "units", text="Units")
919
920         col = layout.column()
921         col.prop(camera, "distortion_model", text="Lens Distortion")
922         if camera.distortion_model == 'POLYNOMIAL':
923             col = layout.column(align=True)
924             col.prop(camera, "k1")
925             col.prop(camera, "k2")
926             col.prop(camera, "k3")
927         elif camera.distortion_model == 'DIVISION':
928             col = layout.column(align=True)
929             col.prop(camera, "division_k1")
930             col.prop(camera, "division_k2")
931
932
933 class CLIP_PT_marker(CLIP_PT_tracking_panel, Panel):
934     bl_space_type = 'CLIP_EDITOR'
935     bl_region_type = 'UI'
936     bl_category = "Track"
937     bl_label = "Marker"
938     bl_options = {'DEFAULT_CLOSED'}
939
940     def draw(self, context):
941         layout = self.layout
942         layout.use_property_split = True
943         layout.use_property_decorate = False
944
945         sc = context.space_data
946         clip = context.space_data.clip
947         act_track = clip.tracking.tracks.active
948
949         if act_track:
950             layout.template_marker(sc, "clip", sc.clip_user, act_track, compact=False)
951         else:
952             layout.active = False
953             layout.label(text="No active track")
954
955
956 class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel):
957     bl_space_type = 'CLIP_EDITOR'
958     bl_region_type = 'UI'
959     bl_label = "2D Stabilization"
960     bl_category = "Stabilization"
961
962     @classmethod
963     def poll(cls, context):
964         if CLIP_PT_clip_view_panel.poll(context):
965             sc = context.space_data
966
967             return sc.mode == 'TRACKING' and sc.clip
968
969         return False
970
971     def draw_header(self, context):
972         stab = context.space_data.clip.tracking.stabilization
973
974         self.layout.prop(stab, "use_2d_stabilization", text="")
975
976     def draw(self, context):
977         layout = self.layout
978         layout.use_property_split = True
979         layout.use_property_decorate = False
980
981         tracking = context.space_data.clip.tracking
982         stab = tracking.stabilization
983
984         layout.active = stab.use_2d_stabilization
985
986         layout.prop(stab, "anchor_frame")
987
988         row = layout.row(align=True)
989         row.prop(stab, "use_stabilize_rotation", text="Rotation")
990         sub = row.row(align=True)
991         sub.active = stab.use_stabilize_rotation
992         sub.prop(stab, "use_stabilize_scale", text="Scale")
993
994         box = layout.box()
995         row = box.row(align=True)
996         row.prop(stab, "show_tracks_expanded", text="", emboss=False)
997
998         if not stab.show_tracks_expanded:
999             row.label(text="Tracks For Stabilization")
1000         else:
1001             row.label(text="Tracks For Location")
1002             row = box.row()
1003             row.template_list("UI_UL_list", "stabilization_tracks", stab, "tracks",
1004                               stab, "active_track_index", rows=2)
1005
1006             sub = row.column(align=True)
1007
1008             sub.operator("clip.stabilize_2d_add", icon='ADD', text="")
1009             sub.operator("clip.stabilize_2d_remove", icon='REMOVE', text="")
1010
1011             sub.menu('CLIP_MT_stabilize_2d_specials', text="",
1012                      icon='DOWNARROW_HLT')
1013
1014             # Usually we don't hide things from iterface, but here every pixel of
1015             # vertical space is precious.
1016             if stab.use_stabilize_rotation:
1017                 box.label(text="Tracks For Rotation / Scale")
1018                 row = box.row()
1019                 row.template_list("UI_UL_list", "stabilization_rotation_tracks",
1020                                   stab, "rotation_tracks",
1021                                   stab, "active_rotation_track_index", rows=2)
1022
1023                 sub = row.column(align=True)
1024
1025                 sub.operator("clip.stabilize_2d_rotation_add", icon='ADD', text="")
1026                 sub.operator("clip.stabilize_2d_rotation_remove", icon='REMOVE', text="")
1027
1028                 sub.menu('CLIP_MT_stabilize_2d_rotation_specials', text="",
1029                          icon='DOWNARROW_HLT')
1030
1031         col = layout.column()
1032         col.prop(stab, "use_autoscale")
1033         sub = col.row()
1034         sub.active = stab.use_autoscale
1035         sub.prop(stab, "scale_max", text="Max")
1036
1037         col = layout.column(align=True)
1038         row = col.row(align=True)
1039         row.prop(stab, "target_position", text="Target")
1040         col.prop(stab, "target_rotation")
1041         row = col.row(align=True)
1042         row.prop(stab, "target_scale")
1043         row.active = not stab.use_autoscale
1044
1045         col = layout.column(align=True)
1046         col.prop(stab, "influence_location")
1047         sub = col.column(align=True)
1048         sub.active = stab.use_stabilize_rotation
1049         sub.prop(stab, "influence_rotation")
1050         sub.prop(stab, "influence_scale")
1051
1052         layout.prop(stab, "filter_type")
1053
1054
1055 class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel):
1056     bl_space_type = 'CLIP_EDITOR'
1057     bl_region_type = 'UI'
1058     bl_category = "Footage"
1059     bl_label = "Proxy/Timecode"
1060     bl_options = {'DEFAULT_CLOSED'}
1061
1062     def draw_header(self, context):
1063         sc = context.space_data
1064
1065         self.layout.prop(sc.clip, "use_proxy", text="")
1066
1067     def draw(self, context):
1068         layout = self.layout
1069
1070         sc = context.space_data
1071         clip = sc.clip
1072
1073         col = layout.column()
1074         col.active = clip.use_proxy
1075
1076         col.label(text="Build Original:")
1077
1078         row = col.row(align=True)
1079         row.prop(clip.proxy, "build_25", toggle=True)
1080         row.prop(clip.proxy, "build_50", toggle=True)
1081         row.prop(clip.proxy, "build_75", toggle=True)
1082         row.prop(clip.proxy, "build_100", toggle=True)
1083
1084         col.label(text="Build Undistorted:")
1085
1086         row = col.row(align=True)
1087         row.prop(clip.proxy, "build_undistorted_25", toggle=True)
1088         row.prop(clip.proxy, "build_undistorted_50", toggle=True)
1089         row.prop(clip.proxy, "build_undistorted_75", toggle=True)
1090         row.prop(clip.proxy, "build_undistorted_100", toggle=True)
1091
1092         layout.use_property_split = True
1093         layout.use_property_decorate = False
1094         col = layout.column()
1095         col.prop(clip.proxy, "quality")
1096
1097         col.prop(clip, "use_proxy_custom_directory")
1098         if clip.use_proxy_custom_directory:
1099             col.prop(clip.proxy, "directory")
1100
1101         col.operator(
1102             "clip.rebuild_proxy",
1103             text="Build Proxy / Timecode" if clip.source == 'MOVIE'
1104             else "Build Proxy"
1105         )
1106
1107         if clip.source == 'MOVIE':
1108             col2 = col.column()
1109             col2.prop(clip.proxy, "timecode", text="Timecode Index")
1110
1111         col.separator()
1112
1113         col.prop(sc.clip_user, "proxy_render_size", text="Proxy Size")
1114
1115
1116 # -----------------------------------------------------------------------------
1117 # Mask (similar code in space_image.py, keep in sync)
1118
1119 from .properties_mask_common import (
1120     MASK_PT_mask,
1121     MASK_PT_layers,
1122     MASK_PT_spline,
1123     MASK_PT_point,
1124     MASK_PT_display,
1125     MASK_PT_transforms,
1126 )
1127
1128
1129 class CLIP_PT_mask_layers(MASK_PT_layers, Panel):
1130     bl_space_type = 'CLIP_EDITOR'
1131     bl_region_type = 'UI'
1132     bl_category = "Mask"
1133
1134
1135 class CLIP_PT_mask_display(MASK_PT_display, Panel):
1136     bl_space_type = 'CLIP_EDITOR'
1137     bl_region_type = 'HEADER'
1138     bl_category = "Mask"
1139
1140
1141 class CLIP_PT_active_mask_spline(MASK_PT_spline, Panel):
1142     bl_space_type = 'CLIP_EDITOR'
1143     bl_region_type = 'UI'
1144     bl_category = "Mask"
1145
1146
1147 class CLIP_PT_active_mask_point(MASK_PT_point, Panel):
1148     bl_space_type = 'CLIP_EDITOR'
1149     bl_region_type = 'UI'
1150     bl_category = "Mask"
1151
1152
1153 class CLIP_PT_mask(MASK_PT_mask, Panel):
1154     bl_space_type = 'CLIP_EDITOR'
1155     bl_region_type = 'UI'
1156     bl_category = "Mask"
1157
1158
1159 class CLIP_PT_tools_mask_transforms(MASK_PT_transforms, Panel):
1160     bl_space_type = 'CLIP_EDITOR'
1161     bl_region_type = 'TOOLS'
1162     bl_category = "Mask"
1163
1164
1165 # --- end mask ---
1166
1167
1168 class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel):
1169     bl_space_type = 'CLIP_EDITOR'
1170     bl_region_type = 'UI'
1171     bl_category = "Footage"
1172     bl_label = "Footage Settings"
1173
1174     def draw(self, context):
1175         layout = self.layout
1176         layout.use_property_split = True
1177         layout.use_property_decorate = False
1178
1179         sc = context.space_data
1180         clip = sc.clip
1181
1182         col = layout.column()
1183         col.template_movieclip(sc, "clip", compact=True)
1184         col.prop(clip, "frame_start")
1185         col.prop(clip, "frame_offset")
1186         col.template_movieclip_information(sc, "clip", sc.clip_user)
1187
1188
1189 class CLIP_PT_tools_scenesetup(Panel):
1190     bl_space_type = 'CLIP_EDITOR'
1191     bl_region_type = 'TOOLS'
1192     bl_label = "Scene Setup"
1193     bl_translation_context = bpy.app.translations.contexts.id_movieclip
1194     bl_category = "Solve"
1195
1196     @classmethod
1197     def poll(cls, context):
1198         sc = context.space_data
1199         clip = sc.clip
1200
1201         return clip and sc.view == 'CLIP' and sc.mode != 'MASK'
1202
1203     def draw(self, context):
1204         layout = self.layout
1205
1206         layout.operator("clip.set_viewport_background")
1207         layout.operator("clip.setup_tracking_scene")
1208
1209
1210 # Grease Pencil properties
1211 class CLIP_PT_grease_pencil(AnnotationDataPanel, CLIP_PT_clip_view_panel, Panel):
1212     bl_space_type = 'CLIP_EDITOR'
1213     bl_region_type = 'UI'
1214     bl_category = "Annotation"
1215     bl_options = set()
1216
1217     # NOTE: this is just a wrapper around the generic GP Panel
1218     # But, this should only be visible in "clip" view
1219
1220
1221 # Grease Pencil drawing tools
1222 class CLIP_PT_tools_grease_pencil_draw(AnnotationDrawingToolsPanel, Panel):
1223     bl_space_type = 'CLIP_EDITOR'
1224     bl_region_type = 'TOOLS'
1225
1226
1227 class CLIP_MT_view(Menu):
1228     bl_label = "View"
1229
1230     def draw(self, context):
1231         layout = self.layout
1232
1233         sc = context.space_data
1234
1235         if sc.view == 'CLIP':
1236             layout.operator("clip.properties", icon='MENU_PANEL')
1237             layout.operator("clip.tools", icon='MENU_PANEL')
1238             layout.separator()
1239
1240             layout.operator("clip.view_selected")
1241             layout.operator("clip.view_all")
1242             layout.operator("clip.view_all", text="View Fit").fit_view = True
1243
1244             layout.separator()
1245             layout.operator("clip.view_zoom_in")
1246             layout.operator("clip.view_zoom_out")
1247
1248             layout.separator()
1249             layout.prop(sc, "show_metadata")
1250             layout.separator()
1251
1252             ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1))
1253
1254             text = iface_("Zoom %d:%d")
1255             for a, b in ratios:
1256                 layout.operator("clip.view_zoom_ratio",
1257                                 text=text % (a, b),
1258                                 translate=False).ratio = a / b
1259         else:
1260             if sc.view == 'GRAPH':
1261                 layout.operator_context = 'INVOKE_REGION_PREVIEW'
1262                 layout.operator("clip.graph_center_current_frame")
1263                 layout.operator("clip.graph_view_all")
1264                 layout.operator_context = 'INVOKE_DEFAULT'
1265
1266             layout.prop(sc, "show_seconds")
1267             layout.prop(sc, "show_locked_time")
1268
1269         layout.separator()
1270
1271         layout.menu("INFO_MT_area")
1272
1273
1274 class CLIP_MT_clip(Menu):
1275     bl_label = "Clip"
1276     bl_translation_context = bpy.app.translations.contexts.id_movieclip
1277
1278     def draw(self, context):
1279         layout = self.layout
1280
1281         sc = context.space_data
1282         clip = sc.clip
1283
1284         layout.operator("clip.open")
1285
1286         if clip:
1287             layout.operator("clip.prefetch")
1288             layout.operator("clip.reload")
1289             layout.menu("CLIP_MT_proxy")
1290
1291
1292 class CLIP_MT_proxy(Menu):
1293     bl_label = "Proxy"
1294
1295     def draw(self, context):
1296         layout = self.layout
1297
1298         layout.operator("clip.rebuild_proxy")
1299         layout.operator("clip.delete_proxy")
1300
1301
1302 class CLIP_MT_track(Menu):
1303     bl_label = "Track"
1304
1305     def draw(self, context):
1306         layout = self.layout
1307
1308         layout.operator("clip.clear_solution")
1309         layout.operator("clip.solve_camera")
1310
1311         layout.separator()
1312         props = layout.operator("clip.clear_track_path", text="Clear After")
1313         props.clear_active = False
1314         props.action = 'REMAINED'
1315
1316         props = layout.operator("clip.clear_track_path", text="Clear Before")
1317         props.clear_active = False
1318         props.action = 'UPTO'
1319
1320         props = layout.operator("clip.clear_track_path", text="Clear Track Path")
1321         props.clear_active = False
1322         props.action = 'ALL'
1323
1324         layout.separator()
1325         layout.operator("clip.join_tracks")
1326
1327         layout.separator()
1328         layout.operator("clip.clean_tracks")
1329
1330         layout.separator()
1331         layout.operator("clip.copy_tracks")
1332         layout.operator("clip.paste_tracks")
1333
1334         layout.separator()
1335         props = layout.operator("clip.track_markers", text="Track Frame Backwards")
1336         props.backwards = True
1337         props.sequence = False
1338
1339         props = layout.operator("clip.track_markers", text="Track Backwards")
1340         props.backwards = True
1341         props.sequence = True
1342
1343         props = layout.operator("clip.track_markers", text="Track Forwards")
1344         props.backwards = False
1345         props.sequence = True
1346
1347         props = layout.operator("clip.track_markers", text="Track Frame Forwards")
1348         props.backwards = False
1349         props.sequence = False
1350
1351         layout.separator()
1352         layout.operator("clip.delete_track")
1353         layout.operator("clip.delete_marker")
1354
1355         layout.separator()
1356         layout.operator("clip.add_marker_move")
1357
1358         layout.separator()
1359         layout.menu("CLIP_MT_track_visibility")
1360         layout.menu("CLIP_MT_track_transform")
1361
1362
1363 class CLIP_MT_reconstruction(Menu):
1364     bl_label = "Reconstruction"
1365
1366     def draw(self, context):
1367         layout = self.layout
1368
1369         layout.operator("clip.set_origin")
1370         layout.operator("clip.set_plane", text="Set Floor").plane = 'FLOOR'
1371         layout.operator("clip.set_plane", text="Set Wall").plane = 'WALL'
1372
1373         layout.operator("clip.set_axis", text="Set X Axis").axis = 'X'
1374         layout.operator("clip.set_axis", text="Set Y Axis").axis = 'Y'
1375
1376         layout.operator("clip.set_scale")
1377
1378         layout.separator()
1379
1380         layout.operator("clip.track_to_empty")
1381         layout.operator("clip.bundles_to_mesh")
1382
1383
1384 class CLIP_MT_track_visibility(Menu):
1385     bl_label = "Show/Hide"
1386
1387     def draw(self, context):
1388         layout = self.layout
1389
1390         layout.operator("clip.hide_tracks_clear", text="Show Hidden")
1391         layout.operator("clip.hide_tracks", text="Hide Selected").unselected = False
1392         layout.operator("clip.hide_tracks", text="Hide Unselected").unselected = True
1393
1394
1395 class CLIP_MT_track_transform(Menu):
1396     bl_label = "Transform"
1397
1398     def draw(self, context):
1399         layout = self.layout
1400
1401         layout.operator("transform.translate")
1402         layout.operator("transform.resize")
1403
1404
1405 class CLIP_MT_select(Menu):
1406     bl_label = "Select"
1407
1408     def draw(self, context):
1409         layout = self.layout
1410
1411         layout.operator("clip.select_box")
1412         layout.operator("clip.select_circle")
1413
1414         layout.separator()
1415
1416         layout.operator("clip.select_all"
1417                         ).action = 'TOGGLE'
1418         layout.operator("clip.select_all",
1419                         text="Inverse").action = 'INVERT'
1420
1421         layout.menu("CLIP_MT_select_grouped")
1422
1423
1424 class CLIP_MT_select_grouped(Menu):
1425     bl_label = "Select Grouped"
1426
1427     def draw(self, context):
1428         layout = self.layout
1429
1430         layout.operator_enum("clip.select_grouped", "group")
1431
1432
1433 class CLIP_MT_tracking_specials(Menu):
1434     bl_label = "Specials"
1435
1436     @classmethod
1437     def poll(cls, context):
1438         return context.space_data.clip
1439
1440     def draw(self, context):
1441         layout = self.layout
1442
1443         layout.operator("clip.disable_markers",
1444                         text="Enable Markers").action = 'ENABLE'
1445
1446         layout.operator("clip.disable_markers",
1447                         text="Disable Markers").action = 'DISABLE'
1448
1449         layout.separator()
1450         layout.operator("clip.set_origin")
1451
1452         layout.separator()
1453         layout.operator("clip.hide_tracks")
1454         layout.operator("clip.hide_tracks_clear", text="Show Tracks")
1455
1456         layout.separator()
1457         layout.operator("clip.lock_tracks", text="Lock Tracks").action = 'LOCK'
1458
1459         layout.operator("clip.lock_tracks",
1460                         text="Unlock Tracks").action = 'UNLOCK'
1461
1462
1463 class CLIP_PT_camera_presets(PresetMenu):
1464     """Predefined tracking camera intrinsics"""
1465     bl_label = "Camera Presets"
1466     preset_subdir = "tracking_camera"
1467     preset_operator = "script.execute_preset"
1468     preset_add_operator = "clip.camera_preset_add"
1469
1470
1471 class CLIP_PT_track_color_presets(PresetMenu):
1472     """Predefined track color"""
1473     bl_label = "Color Presets"
1474     preset_subdir = "tracking_track_color"
1475     preset_operator = "script.execute_preset"
1476     preset_add_operator = "clip.track_color_preset_add"
1477
1478
1479 class CLIP_PT_tracking_settings_presets(PresetMenu):
1480     """Predefined tracking settings"""
1481     bl_label = "Tracking Presets"
1482     preset_subdir = "tracking_settings"
1483     preset_operator = "script.execute_preset"
1484     preset_add_operator = "clip.tracking_settings_preset_add"
1485
1486
1487 class CLIP_MT_stabilize_2d_specials(Menu):
1488     bl_label = "Translation Track Specials"
1489
1490     def draw(self, context):
1491         layout = self.layout
1492
1493         layout.operator("clip.stabilize_2d_select")
1494
1495
1496 class CLIP_MT_stabilize_2d_rotation_specials(Menu):
1497     bl_label = "Rotation Track Specials"
1498
1499     def draw(self, context):
1500         layout = self.layout
1501
1502         layout.operator("clip.stabilize_2d_rotation_select")
1503
1504
1505 class CLIP_MT_pivot_pie(Menu):
1506     bl_label = "Pivot Point"
1507
1508     def draw(self, context):
1509         layout = self.layout
1510         pie = layout.menu_pie()
1511
1512         pie.prop_enum(context.space_data, "pivot_point", value='BOUNDING_BOX_CENTER')
1513         pie.prop_enum(context.space_data, "pivot_point", value='CURSOR')
1514         pie.prop_enum(context.space_data, "pivot_point", value='INDIVIDUAL_ORIGINS')
1515         pie.prop_enum(context.space_data, "pivot_point", value='MEDIAN_POINT')
1516
1517
1518 classes = (
1519     CLIP_UL_tracking_objects,
1520     CLIP_HT_header,
1521     CLIP_PT_display,
1522     CLIP_PT_clip_display,
1523     CLIP_PT_marker_display,
1524     CLIP_MT_track,
1525     CLIP_MT_tracking_editor_menus,
1526     CLIP_MT_masking_editor_menus,
1527     CLIP_PT_track,
1528     CLIP_PT_tools_clip,
1529     CLIP_PT_tools_marker,
1530     CLIP_PT_tracking_settings,
1531     CLIP_PT_tracking_settings_extras,
1532     CLIP_PT_tools_tracking,
1533     CLIP_PT_tools_plane_tracking,
1534     CLIP_PT_tools_solve,
1535     CLIP_PT_tools_cleanup,
1536     CLIP_PT_tools_geometry,
1537     CLIP_PT_tools_orientation,
1538     CLIP_PT_tools_object,
1539     CLIP_PT_objects,
1540     CLIP_PT_plane_track,
1541     CLIP_PT_track_settings,
1542     CLIP_PT_track_settings_extras,
1543     CLIP_PT_tracking_camera,
1544     CLIP_PT_tracking_lens,
1545     CLIP_PT_marker,
1546     CLIP_PT_proxy,
1547     CLIP_PT_footage,
1548     CLIP_PT_stabilization,
1549     CLIP_PT_mask,
1550     CLIP_PT_mask_layers,
1551     CLIP_PT_mask_display,
1552     CLIP_PT_active_mask_spline,
1553     CLIP_PT_active_mask_point,
1554     CLIP_PT_tools_mask_transforms,
1555     CLIP_PT_tools_scenesetup,
1556     CLIP_PT_grease_pencil,
1557     CLIP_PT_tools_grease_pencil_draw,
1558     CLIP_MT_view,
1559     CLIP_MT_clip,
1560     CLIP_MT_proxy,
1561     CLIP_MT_reconstruction,
1562     CLIP_MT_track_visibility,
1563     CLIP_MT_track_transform,
1564     CLIP_MT_select,
1565     CLIP_MT_select_grouped,
1566     CLIP_MT_tracking_specials,
1567     CLIP_PT_camera_presets,
1568     CLIP_PT_track_color_presets,
1569     CLIP_PT_tracking_settings_presets,
1570     CLIP_MT_stabilize_2d_specials,
1571     CLIP_MT_stabilize_2d_rotation_specials,
1572     CLIP_MT_pivot_pie,
1573 )
1574
1575 if __name__ == "__main__":  # only for live edit.
1576     from bpy.utils import register_class
1577     for cls in classes:
1578         register_class(cls)