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