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