Camera tracking integration
[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 compliant>
20 import bpy
21
22
23 class CLIP_OT_apply_follow_track(bpy.types.Operator):
24     bl_idname = "clip.apply_follow_track"
25     bl_label = "Apply Follow Track"
26     bl_options = {'UNDO', 'REGISTER'}
27
28     @classmethod
29     def poll(cls, context):
30         if context.space_data.type != 'CLIP_EDITOR':
31             return False
32
33         sc = context.space_data
34         clip = sc.clip
35
36         return clip and clip.tracking.active_track and context.active_object
37
38     def execute(self, context):
39         ob = context.active_object
40         sc = context.space_data
41         clip = sc.clip
42         track = clip.tracking.active_track
43         constraint = None
44
45         for con in ob.constraints:
46             if con.type == 'FOLLOW_TRACK':
47                 constraint = con
48                 break
49
50         if constraint is None:
51             constraint = ob.constraints.new(type='FOLLOW_TRACK')
52
53         constraint.clip = sc.clip
54         constraint.track = track.name
55         constraint.reference = 'TRACK'
56
57         return {'FINISHED'}
58
59
60 class CLIP_OT_bundles_to_mesh(bpy.types.Operator):
61     bl_idname = "clip.bundles_to_mesh"
62     bl_label = "Bundles to Mesh"
63     bl_options = {'UNDO', 'REGISTER'}
64
65     @classmethod
66     def poll(cls, context):
67         if context.space_data.type != 'CLIP_EDITOR':
68             return False
69
70         sc = context.space_data
71         clip = sc.clip
72
73         return clip
74
75     def execute(self, context):
76         sc = context.space_data
77         clip = sc.clip
78
79         mesh = bpy.data.meshes.new(name="Bundles")
80         for track in clip.tracking.tracks:
81             if track.has_bundle:
82                 mesh.vertices.add(1)
83                 mesh.vertices[-1].co = track.bundle
84
85         ob = bpy.data.objects.new(name="Bundles", object_data=mesh)
86
87         bpy.context.scene.objects.link(ob)
88
89         return {'FINISHED'}
90
91
92 class CLIP_HT_header(bpy.types.Header):
93     bl_space_type = 'CLIP_EDITOR'
94
95     def draw(self, context):
96         layout = self.layout
97
98         sc = context.space_data
99         clip = sc.clip
100
101         row = layout.row(align=True)
102         row.template_header()
103
104         if context.area.show_menus:
105             sub = row.row(align=True)
106             sub.menu("CLIP_MT_view")
107             sub.menu("CLIP_MT_clip")
108
109             if clip:
110                 sub.menu("CLIP_MT_select")
111                 sub.menu("CLIP_MT_track")
112
113         layout.template_ID(sc, "clip")
114
115
116 class CLIP_PT_tools(bpy.types.Panel):
117     bl_space_type = 'CLIP_EDITOR'
118     bl_region_type = 'TOOLS'
119     bl_label = "Tools"
120
121     def draw(self, context):
122         layout = self.layout
123         clip = context.space_data.clip
124         settings = clip.tracking.settings
125
126         if clip:
127             col = layout.column(align=True)
128             col.label(text="Transform:")
129             col.operator("transform.translate")
130             col.operator("transform.resize")
131
132             col = layout.column(align=True)
133             col.label(text="Marker:")
134             col.operator("clip.add_marker_move")
135             col.operator("clip.delete_track")
136             col.operator("clip.delete_marker")
137
138             col = layout.column(align=True)
139             col.label(text="2D tracking:")
140             row = col.row(align=True)
141
142             op = row.operator("clip.track_markers", text="", icon='FRAME_PREV')
143             op.backwards = True
144             op = row.operator("clip.track_markers", text="", \
145                  icon='PLAY_REVERSE')
146             op.backwards = True
147             op.sequence = True
148             op = row.operator("clip.track_markers", text="", icon='PLAY')
149             op.sequence = True
150             row.operator("clip.track_markers", text="", icon='FRAME_NEXT')
151
152             col = layout.column(align=True)
153             op = col.operator("clip.clear_track_path", \
154                  text="Clear Remained Path")
155             op.action = 'REMAINED'
156
157             op = col.operator("clip.clear_track_path", text="Clear Path Up To")
158             op.action = 'UPTO'
159
160             op = col.operator("clip.clear_track_path", text="Clear Track Path")
161             op.action = 'ALL'
162
163             layout.operator("clip.apply_follow_track")
164
165             col = layout.column(align=True)
166             col.label(text="Reconstruction:")
167
168             col.prop(settings, "keyframe1")
169             col.prop(settings, "keyframe2")
170
171             col = layout.column(align=True)
172             col.operator("clip.solve_camera")
173             col.operator("clip.clear_reconstruction")
174
175             col = layout.column(align=True)
176             col.operator("clip.bundles_to_mesh")
177
178             col = layout.column(align=True)
179             col.label(text="Scene Orientation:")
180             col.operator("clip.set_floor")
181             col.operator("clip.set_origin")
182
183             row = col.row()
184             row.operator("clip.set_axis", text="Set X Axis").axis = 'X'
185             row.operator("clip.set_axis", text="Set Y Axis").axis = 'Y'
186         else:
187             layout.operator('clip.open')
188
189
190 class CLIP_PT_track(bpy.types.Panel):
191     bl_space_type = 'CLIP_EDITOR'
192     bl_region_type = 'UI'
193     bl_label = "Track"
194
195     @classmethod
196     def poll(cls, context):
197         sc = context.space_data
198         clip = sc.clip
199
200         return clip and clip.tracking.active_track
201
202     def draw(self, context):
203         layout = self.layout
204         sc = context.space_data
205         clip = context.space_data.clip
206         act_track = clip.tracking.active_track
207
208         layout.prop(act_track, "name")
209
210         layout.template_track(clip.tracking, "active_track", \
211             sc.clip_user, clip)
212
213         if act_track:
214             row = layout.row()
215             row.prop(act_track, "use_red_channel", text="Red")
216             row.prop(act_track, "use_green_channel", text="Green")
217             row.prop(act_track, "use_blue_channel", text="Blue")
218
219
220 class CLIP_PT_track_settings(bpy.types.Panel):
221     bl_space_type = 'CLIP_EDITOR'
222     bl_region_type = 'UI'
223     bl_label = "Tracking Settings"
224     bl_options = {'DEFAULT_CLOSED'}
225
226     @classmethod
227     def poll(cls, context):
228         sc = context.space_data
229
230         return sc.clip
231
232     def draw(self, context):
233         layout = self.layout
234         clip = context.space_data.clip
235         settings = clip.tracking.settings
236
237         layout.label(text="2D tracking:")
238         layout.prop(settings, "speed")
239         layout.prop(settings, "use_frames_limit")
240
241         row = layout.row()
242         row.active = settings.use_frames_limit
243         row.prop(settings, "frames_limit")
244
245
246 class CLIP_PT_tracking_camera(bpy.types.Panel):
247     bl_space_type = 'CLIP_EDITOR'
248     bl_region_type = 'UI'
249     bl_label = "Camera Data"
250     bl_options = {'DEFAULT_CLOSED'}
251
252     @classmethod
253     def poll(cls, context):
254         sc = context.space_data
255
256         return sc.clip
257
258     def draw(self, context):
259         layout = self.layout
260
261         sc = context.space_data
262         clip = sc.clip
263
264         layout.prop(clip.tracking.camera, "sensor_width")
265
266         row = layout.row(align=True)
267         sub = row.split(percentage=0.65)
268         sub.prop(clip.tracking.camera, "focal_length")
269         sub.prop(clip.tracking.camera, "units", text="")
270
271         layout.label(text="Principal Point")
272         layout.prop(clip.tracking.camera, "principal", text="")
273
274         col = layout.column(align=True)
275         col.prop(clip.tracking.camera, "k1")
276         col.prop(clip.tracking.camera, "k2")
277         col.prop(clip.tracking.camera, "k3")
278
279
280 class CLIP_PT_display(bpy.types.Panel):
281     bl_space_type = 'CLIP_EDITOR'
282     bl_region_type = 'UI'
283     bl_label = "Display"
284     bl_options = {'DEFAULT_CLOSED'}
285
286     def draw(self, context):
287         layout = self.layout
288         sc = context.space_data
289
290         row = layout.row()
291         row.prop(sc, "show_marker_pattern", text="Pattern")
292         row.prop(sc, "show_marker_search", text="Search")
293
294         row = layout.row()
295         row.prop(sc, "show_track_path", text="Path")
296         row.active = sc.show_track_path
297         row.prop(sc, "path_length", text="Length")
298
299         layout.prop(sc, "show_tiny_markers", text="Tiny Markers")
300         layout.prop(sc, "show_bundles", text="Bundles")
301
302         layout.prop(sc, "lock_selection")
303         layout.prop(sc, "use_mute_footage")
304
305
306 class CLIP_PT_footage(bpy.types.Panel):
307     bl_space_type = 'CLIP_EDITOR'
308     bl_region_type = 'UI'
309     bl_label = "Footage Settings"
310     bl_options = {'DEFAULT_CLOSED'}
311
312     @classmethod
313     def poll(cls, context):
314         sc = context.space_data
315
316         return sc.clip
317
318     def draw(self, context):
319         layout = self.layout
320
321         sc = context.space_data
322         clip = sc.clip
323
324         if clip:
325             layout.template_movieclip(sc, "clip", sc.clip_user, compact=True)
326         else:
327             layout.operator("clip.open", icon='FILESEL')
328
329
330 class CLIP_MT_view(bpy.types.Menu):
331     bl_label = "View"
332
333     def draw(self, context):
334         layout = self.layout
335
336         layout.operator("clip.properties", icon='MENU_PANEL')
337         layout.operator("clip.tools", icon='MENU_PANEL')
338         layout.separator()
339
340         layout.operator("clip.view_selected")
341         layout.operator("clip.view_all")
342
343         layout.separator()
344         layout.operator("clip.view_zoom_in")
345         layout.operator("clip.view_zoom_out")
346
347         layout.separator()
348
349         ratios = [[1, 8], [1, 4], [1, 2], [1, 1], [2, 1], [4, 1], [8, 1]]
350
351         for a, b in ratios:
352             text = "Zoom %d:%d" % (a, b)
353             layout.operator("clip.view_zoom_ratio", text=text).ratio = a / b
354
355         layout.separator()
356         layout.operator("screen.area_dupli")
357         layout.operator("screen.screen_full_area")
358
359
360 class CLIP_MT_clip(bpy.types.Menu):
361     bl_label = "Clip"
362
363     def draw(self, context):
364         layout = self.layout
365
366         sc = context.space_data
367         clip = sc.clip
368
369         if clip:
370             layout.operator("clip.reload")
371
372         layout.operator("clip.open")
373
374
375 class CLIP_MT_track(bpy.types.Menu):
376     bl_label = "Track"
377
378     def draw(self, context):
379         layout = self.layout
380
381         layout.operator("clip.set_origin")
382
383         layout.separator()
384         layout.operator("clip.clear_reconstruction")
385         layout.operator("clip.solve_camera")
386
387         layout.separator()
388         op = layout.operator("clip.clear_track_path", \
389              text="Clear Remained Path")
390         op.action = 'REMAINED'
391
392         op = layout.operator("clip.clear_track_path", \
393              text="Clear Path Up To")
394         op.action = 'UPTO'
395
396         op = layout.operator("clip.clear_track_path", \
397              text="Clear Track Path")
398         op.action = 'ALL'
399
400         layout.separator()
401         op = layout.operator("clip.track_markers", \
402             text="Track Frame Backwards")
403         op.backwards = True
404
405         op = layout.operator("clip.track_markers", text="Track Backwards")
406         op.backwards = True
407         op.sequence = True
408
409         op = layout.operator("clip.track_markers", text="Track Forwards")
410         op.sequence = True
411         layout.operator("clip.track_markers", text="Track Frame Forwards")
412
413         layout.separator()
414         layout.operator("clip.delete_track")
415         layout.operator("clip.delete_marker")
416
417         layout.separator()
418         layout.operator("clip.add_marker_move")
419
420         layout.separator()
421         layout.menu("CLIP_MT_track_visibility")
422         layout.menu("CLIP_MT_track_transform")
423
424
425 class CLIP_MT_track_visibility(bpy.types.Menu):
426     bl_label = "Show/Hide"
427
428     def draw(self, context):
429         layout = self.layout
430
431         layout.operator("clip.hide_tracks_clear", text="Show Hidden")
432         layout.operator("clip.hide_tracks", text="Hide Selected")
433
434         op = layout.operator("clip.hide_tracks", text="Hide Unselected")
435         op.unselected = True
436
437
438 class CLIP_MT_track_transform(bpy.types.Menu):
439     bl_label = "Transform"
440
441     def draw(self, context):
442         layout = self.layout
443
444         layout.operator("transform.translate")
445         layout.operator("transform.resize")
446
447
448 class CLIP_MT_select(bpy.types.Menu):
449     bl_label = "Select"
450
451     def draw(self, context):
452         layout = self.layout
453
454         sc = context.space_data
455
456         layout.operator("clip.select_border")
457         layout.operator("clip.select_circle")
458         layout.operator("clip.select_all", text="Select/Deselect all")
459         layout.operator("clip.select_all", text="Inverse").action = 'INVERT'
460
461
462 class CLIP_MT_tracking_specials(bpy.types.Menu):
463     bl_label = "Specials"
464
465     @classmethod
466     def poll(cls, context):
467         return context.space_data.clip
468
469     def draw(self, context):
470         layout = self.layout
471
472         op = layout.operator("clip.disable_markers", text="Enable Markers")
473         op.action = 'ENABLE'
474
475         op = layout.operator("clip.disable_markers", text="Disable markers")
476         op.action = 'DISABLE'
477
478         layout.operator("clip.set_origin")
479
480         layout.separator()
481         layout.operator("clip.hide_tracks")
482         layout.operator("clip.hide_tracks_clear", text="Show Tracks")
483
484 if __name__ == "__main__":  # only for live edit.
485     bpy.utils.register_module(__name__)