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