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