1 # ##### BEGIN GPL LICENSE BLOCK #####
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.
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.
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.
17 # ##### END GPL LICENSE BLOCK #####
21 from bpy.types import Panel, Header, Menu
24 class CLIP_HT_header(Header):
25 bl_space_type = 'CLIP_EDITOR'
27 def draw(self, context):
30 sc = context.space_data
33 row = layout.row(align=True)
36 if context.area.show_menus:
37 sub = row.row(align=True)
38 sub.menu("CLIP_MT_view")
41 sub.menu("CLIP_MT_select")
43 sub.menu("CLIP_MT_clip")
46 sub.menu("CLIP_MT_track")
47 sub.menu("CLIP_MT_reconstruction")
50 layout.prop(sc, "mode", text="")
51 layout.prop(sc, "view", text="", expand=True)
53 if sc.view == 'GRAPH':
54 row = layout.row(align=True)
57 row.prop(sc, "show_filters", icon='DISCLOSURE_TRI_DOWN',
61 sub.active = clip.tracking.reconstruction.is_valid
62 sub.prop(sc, "show_graph_frames", icon='SEQUENCE', text="")
64 row.prop(sc, "show_graph_tracks", icon='ANIM', text="")
66 row.prop(sc, "show_filters", icon='DISCLOSURE_TRI_RIGHT',
70 row.template_ID(sc, "clip", open='clip.open')
73 r = clip.tracking.reconstruction
76 layout.label(text="Average solve error: %.4f" %
79 layout.template_running_jobs()
82 class CLIP_PT_tools_marker(Panel):
83 bl_space_type = 'CLIP_EDITOR'
84 bl_region_type = 'TOOLS'
88 def poll(cls, context):
89 sc = context.space_data
92 return clip and sc.mode == 'TRACKING'
94 def draw(self, context):
97 col = layout.column(align=True)
98 col.operator("clip.add_marker_move")
99 col.operator("clip.detect_features")
100 col.operator("clip.delete_track")
103 class CLIP_PT_tools_tracking(Panel):
104 bl_space_type = 'CLIP_EDITOR'
105 bl_region_type = 'TOOLS'
109 def poll(cls, context):
110 sc = context.space_data
113 return clip and sc.mode == 'TRACKING'
115 def draw(self, context):
117 clip = context.space_data.clip
118 settings = clip.tracking.settings
120 row = layout.row(align=True)
122 props = row.operator("clip.track_markers", text="", icon='FRAME_PREV')
123 props.backwards = True
124 props = row.operator("clip.track_markers", text="",
126 props.backwards = True
127 props.sequence = True
128 props = row.operator("clip.track_markers", text="", icon='PLAY')
129 props.sequence = True
130 row.operator("clip.track_markers", text="", icon='FRAME_NEXT')
132 col = layout.column(align=True)
133 props = col.operator("clip.clear_track_path", text="Clear After")
134 props.action = 'REMAINED'
136 props = col.operator("clip.clear_track_path", text="Clear Before")
137 props.action = 'UPTO'
139 props = col.operator("clip.clear_track_path", text="Clear")
142 layout.operator("clip.join_tracks", text="Join")
145 class CLIP_PT_tools_solve(Panel):
146 bl_space_type = 'CLIP_EDITOR'
147 bl_region_type = 'TOOLS'
151 def poll(cls, context):
152 sc = context.space_data
155 return clip and sc.mode == 'TRACKING'
157 def draw(self, context):
159 clip = context.space_data.clip
160 settings = clip.tracking.settings
162 col = layout.column(align=True)
163 col.operator("clip.solve_camera", text="Camera Motion")
164 col.operator("clip.clear_solution")
166 col = layout.column(align=True)
167 col.prop(settings, "keyframe_a")
168 col.prop(settings, "keyframe_b")
170 col = layout.column(align=True)
171 col.label(text="Refine:")
172 col.prop(settings, "refine_intrinsics", text="")
175 class CLIP_PT_tools_cleanup(Panel):
176 bl_space_type = 'CLIP_EDITOR'
177 bl_region_type = 'TOOLS'
178 bl_label = "Clean up"
181 def poll(cls, context):
182 sc = context.space_data
185 return clip and sc.mode == 'TRACKING'
187 def draw(self, context):
189 clip = context.space_data.clip
190 settings = clip.tracking.settings
192 layout.operator("clip.clean_tracks")
194 layout.prop(settings, 'clean_frames', text="Frames")
195 layout.prop(settings, 'clean_error', text="Error")
196 layout.prop(settings, 'clean_action', text="")
199 class CLIP_PT_tools_geometry(Panel):
200 bl_space_type = 'CLIP_EDITOR'
201 bl_region_type = 'TOOLS'
202 bl_label = "Geometry"
205 def poll(cls, context):
206 sc = context.space_data
209 return clip and sc.mode == 'RECONSTRUCTION'
211 def draw(self, context):
214 layout.operator("clip.tracks_to_mesh")
215 layout.operator("clip.track_to_empty")
218 class CLIP_PT_tools_orientation(Panel):
219 bl_space_type = 'CLIP_EDITOR'
220 bl_region_type = 'TOOLS'
221 bl_label = "Orientation"
224 def poll(cls, context):
225 sc = context.space_data
228 return clip and sc.mode == 'RECONSTRUCTION'
230 def draw(self, context):
231 sc = context.space_data
233 settings = sc.clip.tracking.settings
235 col = layout.column(align=True)
236 col.operator("clip.set_floor")
237 col.operator("clip.set_origin")
240 row.operator("clip.set_axis", text="Set X Axis").axis = 'X'
241 row.operator("clip.set_axis", text="Set Y Axis").axis = 'Y'
245 col = layout.column()
246 col.operator("clip.set_scale")
247 col.prop(settings, "distance")
250 class CLIP_PT_tools_grease_pencil(Panel):
251 bl_space_type = 'CLIP_EDITOR'
252 bl_region_type = 'TOOLS'
253 bl_label = "Grease Pencil"
256 def poll(cls, context):
257 sc = context.space_data
260 return clip and sc.mode == 'DISTORTION'
262 def draw(self, context):
265 col = layout.column(align=True)
267 row = col.row(align=True)
268 row.operator("gpencil.draw", text="Draw").mode = 'DRAW'
269 row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
271 row = col.row(align=True)
272 row.operator("gpencil.draw", text="Poly").mode = 'DRAW_POLY'
273 row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
276 row.prop(context.tool_settings, "use_grease_pencil_sessions")
279 class CLIP_PT_track(Panel):
280 bl_space_type = 'CLIP_EDITOR'
281 bl_region_type = 'UI'
285 def poll(cls, context):
286 sc = context.space_data
289 return sc.mode == 'TRACKING' and clip
291 def draw(self, context):
293 sc = context.space_data
294 clip = context.space_data.clip
295 act_track = clip.tracking.tracks.active
298 layout.active = False
299 layout.label(text="No active track")
303 row.prop(act_track, "name", text="")
305 sub = row.row(align=True)
307 sub.template_marker(sc, "clip", sc.clip_user, act_track, True)
309 icon = 'LOCKED' if act_track.lock else 'UNLOCKED'
310 sub.prop(act_track, "lock", text="", icon=icon)
312 layout.template_track(sc, "scopes")
314 row = layout.row(align=True)
315 row.prop(act_track, "use_red_channel", text="R", toggle=True)
316 row.prop(act_track, "use_green_channel", text="G", toggle=True)
317 row.prop(act_track, "use_blue_channel", text="B", toggle=True)
321 row = layout.row(align=True)
322 label = bpy.types.CLIP_MT_track_color_presets.bl_label
323 row.menu('CLIP_MT_track_color_presets', text=label)
324 row.menu('CLIP_MT_track_color_specials', text="", icon='DOWNARROW_HLT')
325 row.operator("clip.track_color_preset_add", text="", icon='ZOOMIN')
326 props = row.operator("clip.track_color_preset_add",
327 text="", icon='ZOOMOUT')
328 props.remove_active = True
331 row.prop(act_track, "use_custom_color")
332 if act_track.use_custom_color:
333 row.prop(act_track, "color", text="")
335 if act_track.has_bundle:
336 label_text = "Average Error: %.4f" % (act_track.average_error)
337 layout.label(text=label_text)
340 class CLIP_PT_tracking_camera(Panel):
341 bl_space_type = 'CLIP_EDITOR'
342 bl_region_type = 'UI'
343 bl_label = "Camera Data"
344 bl_options = {'DEFAULT_CLOSED'}
347 def poll(cls, context):
348 sc = context.space_data
350 return sc.mode in ['TRACKING', 'DISTORTION'] and sc.clip
352 def draw(self, context):
355 sc = context.space_data
358 row = layout.row(align=True)
359 label = bpy.types.CLIP_MT_camera_presets.bl_label
360 row.menu('CLIP_MT_camera_presets', text=label)
361 row.operator("clip.camera_preset_add", text="", icon='ZOOMIN')
362 props = row.operator("clip.camera_preset_add", text="", icon='ZOOMOUT')
363 props.remove_active = True
365 row = layout.row(align=True)
366 sub = row.split(percentage=0.65)
367 if clip.tracking.camera.units == 'MILLIMETERS':
368 sub.prop(clip.tracking.camera, "focal_length")
370 sub.prop(clip.tracking.camera, "focal_length_pixels")
371 sub.prop(clip.tracking.camera, "units", text="")
373 col = layout.column(align=True)
374 col.label(text="Sensor:")
375 col.prop(clip.tracking.camera, "sensor_width", text="Width")
376 col.prop(clip.tracking.camera, "pixel_aspect")
378 col = layout.column()
379 col.label(text="Optical Center:")
381 row.prop(clip.tracking.camera, "principal", text="")
382 col.operator("clip.set_center_principal", text="Center")
384 col = layout.column(align=True)
385 col.label(text="Undistortion:")
386 col.prop(clip.tracking.camera, "k1")
387 col.prop(clip.tracking.camera, "k2")
388 col.prop(clip.tracking.camera, "k3")
391 class CLIP_PT_display(Panel):
392 bl_space_type = 'CLIP_EDITOR'
393 bl_region_type = 'UI'
396 def draw(self, context):
398 sc = context.space_data
400 col = layout.column(align=True)
402 col.prop(sc, "show_marker_pattern", text="Pattern")
403 col.prop(sc, "show_marker_search", text="Search")
404 col.prop(sc, "show_pyramid_levels", text="Pyramid")
406 col.prop(sc, "show_track_path", text="Track Path")
408 row.active = sc.show_track_path
409 row.prop(sc, "path_length", text="Length")
411 col.prop(sc, "show_disabled", "Disabled Tracks")
412 col.prop(sc, "show_bundles", text="Bundles")
414 col.prop(sc, "show_names", text="Track Names and Status")
415 col.prop(sc, "show_tiny_markers", text="Compact Markers")
417 col.prop(sc, "show_grease_pencil", text="Grease Pencil")
418 col.prop(sc, "use_mute_footage", text="Mute")
420 if sc.mode == 'DISTORTION':
421 col.prop(sc, "show_grid", text="Grid")
422 col.prop(sc, "use_manual_calibration")
423 elif sc.mode == 'RECONSTRUCTION':
424 col.prop(sc, "show_stable", text="Stable")
426 col.prop(sc, "lock_selection")
430 col.label(text="Display Aspect Ratio:")
431 col.prop(clip, "display_aspect", text="")
434 class CLIP_PT_track_settings(Panel):
435 bl_space_type = 'CLIP_EDITOR'
436 bl_region_type = 'UI'
437 bl_label = "Tracking Settings"
438 bl_options = {'DEFAULT_CLOSED'}
441 def poll(cls, context):
442 sc = context.space_data
444 return sc.mode == 'TRACKING' and sc.clip
446 def draw(self, context):
448 clip = context.space_data.clip
449 settings = clip.tracking.settings
451 active = clip.tracking.tracks.active
453 layout.prop(active, "tracker")
454 if active.tracker == 'KLT':
455 layout.prop(active, "pyramid_levels")
456 elif active.tracker == 'SAD':
457 layout.prop(active, "correlation_min")
459 layout.prop(settings, "frames_adjust")
460 layout.prop(settings, "speed")
461 layout.prop(settings, "frames_limit")
462 layout.prop(settings, "margin")
465 class CLIP_PT_stabilization(Panel):
466 bl_space_type = 'CLIP_EDITOR'
467 bl_region_type = 'UI'
468 bl_label = "2D Stabilization"
469 bl_options = {'DEFAULT_CLOSED'}
472 def poll(cls, context):
473 sc = context.space_data
475 return sc.mode == 'RECONSTRUCTION' and sc.clip
477 def draw_header(self, context):
478 sc = context.space_data
479 tracking = sc.clip.tracking
480 stab = tracking.stabilization
482 self.layout.prop(stab, "use_2d_stabilization", text="")
484 def draw(self, context):
486 sc = context.space_data
487 tracking = sc.clip.tracking
488 stab = tracking.stabilization
490 layout.active = stab.use_2d_stabilization
493 row.template_list(stab, "tracks", stab, "active_track_index", rows=3)
495 sub = row.column(align=True)
497 sub.operator("clip.stabilize_2d_add", icon='ZOOMIN', text="")
498 sub.operator("clip.stabilize_2d_remove", icon='ZOOMOUT', text="")
500 sub.menu('CLIP_MT_stabilize_2d_specials', text="",
501 icon='DOWNARROW_HLT')
503 layout.prop(stab, "influence_location")
505 layout.prop(stab, "use_autoscale")
506 col = layout.column()
507 col.active = stab.use_autoscale
508 col.prop(stab, "scale_max")
509 col.prop(stab, "influence_scale")
511 layout.prop(stab, "use_stabilize_rotation")
512 col = layout.column()
513 col.active = stab.use_stabilize_rotation
515 row = col.row(align=True)
516 row.prop_search(stab, "rotation_track", tracking, "tracks", text="")
517 row.operator("clip.stabilize_2d_set_rotation", text="", icon='ZOOMIN')
520 row.active = stab.rotation_track is not None
521 row.prop(stab, "influence_rotation")
524 class CLIP_PT_marker(Panel):
525 bl_space_type = 'CLIP_EDITOR'
526 bl_region_type = 'UI'
528 bl_options = {'DEFAULT_CLOSED'}
531 def poll(cls, context):
532 sc = context.space_data
535 return sc.mode == 'TRACKING' and clip
537 def draw(self, context):
539 sc = context.space_data
540 clip = context.space_data.clip
541 act_track = clip.tracking.tracks.active
544 layout.template_marker(sc, "clip", sc.clip_user, act_track, False)
546 layout.active = False
547 layout.label(text="No active track")
550 class CLIP_PT_proxy(Panel):
551 bl_space_type = 'CLIP_EDITOR'
552 bl_region_type = 'UI'
553 bl_label = "Proxy / Timecode"
554 bl_options = {'DEFAULT_CLOSED'}
557 def poll(cls, context):
558 sc = context.space_data
562 def draw_header(self, context):
563 sc = context.space_data
565 self.layout.prop(sc.clip, "use_proxy", text="")
567 def draw(self, context):
569 sc = context.space_data
572 layout.active = clip.use_proxy
574 layout.label(text="Build Sizes:")
577 row.prop(clip.proxy, "build_25")
578 row.prop(clip.proxy, "build_50")
581 row.prop(clip.proxy, "build_75")
582 row.prop(clip.proxy, "build_100")
584 layout.prop(clip.proxy, "build_undistorted")
586 layout.prop(clip.proxy, "quality")
588 layout.prop(clip, 'use_proxy_custom_directory')
589 if clip.use_proxy_custom_directory:
590 layout.prop(clip.proxy, "directory")
592 layout.operator("clip.rebuild_proxy", text="Rebuild Proxy")
594 if clip.source == 'MOVIE':
595 col = layout.column()
597 col.label(text="Use timecode index:")
598 col.prop(clip.proxy, "timecode", text="")
600 col = layout.column()
601 col.label(text="Proxy render size:")
603 col.prop(sc.clip_user, "proxy_render_size", text="")
604 col.prop(sc.clip_user, "use_render_undistorted")
607 class CLIP_PT_footage(Panel):
608 bl_space_type = 'CLIP_EDITOR'
609 bl_region_type = 'UI'
610 bl_label = "Footage Settings"
611 bl_options = {'DEFAULT_CLOSED'}
614 def poll(cls, context):
615 sc = context.space_data
619 def draw(self, context):
622 sc = context.space_data
626 layout.template_movieclip(sc, "clip", compact=True)
628 layout.operator("clip.open", icon='FILESEL')
631 class CLIP_PT_tools_clip(Panel):
632 bl_space_type = 'CLIP_EDITOR'
633 bl_region_type = 'TOOLS'
637 def poll(cls, context):
638 sc = context.space_data
642 def draw(self, context):
644 clip = context.space_data.clip
646 layout.operator("clip.set_viewport_background")
649 class CLIP_MT_view(Menu):
652 def draw(self, context):
655 layout.operator("clip.properties", icon='MENU_PANEL')
656 layout.operator("clip.tools", icon='MENU_PANEL')
659 layout.operator("clip.view_selected")
660 layout.operator("clip.view_all")
663 layout.operator("clip.view_zoom_in")
664 layout.operator("clip.view_zoom_out")
668 ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1))
671 text = "Zoom %d:%d" % (a, b)
672 layout.operator("clip.view_zoom_ratio", text=text).ratio = a / b
675 layout.operator("screen.area_dupli")
676 layout.operator("screen.screen_full_area")
679 class CLIP_MT_clip(Menu):
682 def draw(self, context):
685 sc = context.space_data
688 layout.operator("clip.open")
691 layout.operator("clip.reload")
692 layout.menu("CLIP_MT_proxy")
695 class CLIP_MT_proxy(Menu):
698 def draw(self, context):
701 sc = context.space_data
704 layout.operator("clip.rebuild_proxy")
705 layout.operator("clip.delete_proxy")
708 class CLIP_MT_track(Menu):
711 def draw(self, context):
714 layout.operator("clip.clear_solution")
715 layout.operator("clip.solve_camera")
718 props = layout.operator("clip.clear_track_path", text="Clear After")
719 props.action = 'REMAINED'
721 props = layout.operator("clip.clear_track_path", text="Clear Before")
722 props.action = 'UPTO'
724 props = layout.operator("clip.clear_track_path",
725 text="Clear Track Path")
729 layout.operator("clip.join_tracks")
732 layout.operator("clip.clean_tracks")
735 props = layout.operator("clip.track_markers",
736 text="Track Frame Backwards")
737 props.backwards = True
739 props = layout.operator("clip.track_markers", text="Track Backwards")
740 props.backwards = True
741 props.sequence = True
743 props = layout.operator("clip.track_markers", text="Track Forwards")
744 props.sequence = True
745 layout.operator("clip.track_markers", text="Track Frame Forwards")
748 layout.operator("clip.delete_track")
749 layout.operator("clip.delete_marker")
752 layout.operator("clip.add_marker_move")
755 layout.menu("CLIP_MT_track_visibility")
756 layout.menu("CLIP_MT_track_transform")
759 class CLIP_MT_reconstruction(Menu):
760 bl_label = "Reconstruction"
762 def draw(self, context):
765 layout.operator("clip.set_origin")
766 layout.operator("clip.set_floor")
768 layout.operator("clip.set_axis", text="Set X Axis").axis = "X"
769 layout.operator("clip.set_axis", text="Set Y Axis").axis = "Y"
771 layout.operator("clip.set_scale")
775 layout.operator("clip.track_to_empty")
776 layout.operator("clip.tracks_to_mesh")
779 class CLIP_MT_track_visibility(Menu):
780 bl_label = "Show/Hide"
782 def draw(self, context):
785 layout.operator("clip.hide_tracks_clear", text="Show Hidden")
786 layout.operator("clip.hide_tracks", text="Hide Selected")
788 props = layout.operator("clip.hide_tracks", text="Hide Unselected")
789 props.unselected = True
792 class CLIP_MT_track_transform(Menu):
793 bl_label = "Transform"
795 def draw(self, context):
798 layout.operator("transform.translate")
799 layout.operator("transform.resize")
802 class CLIP_MT_select(Menu):
805 def draw(self, context):
808 sc = context.space_data
810 layout.operator("clip.select_border")
811 layout.operator("clip.select_circle")
815 layout.operator("clip.select_all", text="Select/Deselect all")
816 layout.operator("clip.select_all", text="Inverse").action = 'INVERT'
818 layout.menu("CLIP_MT_select_grouped")
821 class CLIP_MT_select_grouped(Menu):
822 bl_label = "Select Grouped"
824 def draw(self, context):
827 layout.operator_enum("clip.select_grouped", "group")
830 class CLIP_MT_tracking_specials(Menu):
831 bl_label = "Specials"
834 def poll(cls, context):
835 return context.space_data.clip
837 def draw(self, context):
840 props = layout.operator("clip.disable_markers", text="Enable Markers")
841 props.action = 'ENABLE'
843 props = layout.operator("clip.disable_markers", text="Disable markers")
844 props.action = 'DISABLE'
847 layout.operator("clip.set_origin")
850 layout.operator("clip.hide_tracks")
851 layout.operator("clip.hide_tracks_clear", text="Show Tracks")
854 props = layout.operator("clip.lock_tracks", text="Lock Tracks")
855 props.action = 'LOCK'
857 props = layout.operator("clip.lock_tracks", text="Unlock Tracks")
858 props.action = 'UNLOCK'
861 class CLIP_MT_camera_presets(Menu):
862 """Predefined tracking camera intrinsics"""
863 bl_label = "Camera Presets"
864 preset_subdir = "tracking_camera"
865 preset_operator = "script.execute_preset"
866 draw = bpy.types.Menu.draw_preset
869 class CLIP_MT_track_color_presets(Menu):
870 """Predefined track color"""
871 bl_label = "Color Presets"
872 preset_subdir = "tracking_track_color"
873 preset_operator = "script.execute_preset"
874 draw = bpy.types.Menu.draw_preset
877 class CLIP_MT_track_color_specials(Menu):
878 bl_label = "Track Color Specials"
880 def draw(self, context):
883 layout.operator('clip.track_copy_color', icon='COPY_ID')
886 class CLIP_MT_stabilize_2d_specials(Menu):
887 bl_label = "Track Color Specials"
889 def draw(self, context):
892 layout.operator('clip.stabilize_2d_select')
894 if __name__ == "__main__": # only for live edit.
895 bpy.utils.register_module(__name__)