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