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 #####
23 from bpy.types import Operator
24 from bpy_extras.io_utils import unpack_list
27 def CLIP_track_view_selected(sc, track):
28 if track.select_anchor:
31 if sc.show_marker_pattern and track.select_pattern:
34 if sc.show_marker_search and track.select_search:
40 class CLIP_OT_track_to_empty(Operator):
41 """Create an Empty object which will be copying movement of active track"""
43 bl_idname = "clip.track_to_empty"
44 bl_label = "Link Empty to Track"
45 bl_options = {'UNDO', 'REGISTER'}
47 def _link_track(self, context, track):
48 sc = context.space_data
52 ob = bpy.data.objects.new(name=track.name, object_data=None)
54 bpy.context.scene.objects.link(ob)
55 bpy.context.scene.objects.active = ob
57 for con in ob.constraints:
58 if con.type == 'FOLLOW_TRACK':
62 if constraint is None:
63 constraint = ob.constraints.new(type='FOLLOW_TRACK')
65 constraint.clip = sc.clip
66 constraint.track = track.name
67 constraint.use_3d_position = False
69 def execute(self, context):
70 sc = context.space_data
73 for track in clip.tracking.tracks:
74 if CLIP_track_view_selected(sc, track):
75 self._link_track(context, track)
80 class CLIP_OT_tracks_to_mesh(Operator):
81 """Create vertex cloud using coordinates of tracks"""
83 bl_idname = "clip.tracks_to_mesh"
84 bl_label = "Tracks to Mesh"
85 bl_options = {'UNDO', 'REGISTER'}
88 def poll(cls, context):
89 sc = context.space_data
90 return (sc.type == 'CLIP_EDITOR') and sc.clip
92 def execute(self, context):
93 sc = context.space_data
98 mesh = bpy.data.meshes.new(name="Tracks")
99 for track in clip.tracking.tracks:
101 new_verts.append(track.bundle)
104 mesh.vertices.add(len(new_verts))
105 mesh.vertices.foreach_set("co", unpack_list(new_verts))
107 ob = bpy.data.objects.new(name="Tracks", object_data=mesh)
109 bpy.context.scene.objects.link(ob)
114 class CLIP_OT_delete_proxy(Operator):
115 """Delete movie clip proxy files from the hard drive"""
117 bl_idname = "clip.delete_proxy"
118 bl_label = "Delete Proxy"
119 bl_options = {'UNDO', 'REGISTER'}
122 def poll(cls, context):
123 if context.space_data.type != 'CLIP_EDITOR':
126 sc = context.space_data
130 def invoke(self, context, event):
131 wm = context.window_manager
133 return wm.invoke_confirm(self, event)
135 def _rmproxy(self, abspath):
136 if not os.path.exists(abspath):
139 if os.path.isdir(abspath):
140 shutil.rmtree(abspath)
144 def execute(self, context):
145 sc = context.space_data
147 if clip.use_proxy_custom_directory:
148 proxydir = clip.proxy.directory
150 clipdir = os.path.dirname(clip.filepath)
151 proxydir = os.path.join(clipdir, 'BL_proxy')
153 clipfile = os.path.basename(clip.filepath)
154 proxy = os.path.join(proxydir, clipfile)
155 absproxy = bpy.path.abspath(proxy)
157 # proxy_<quality>[_undostorted]
158 for x in (25, 50, 75, 100):
159 d = os.path.join(absproxy, 'proxy_' + str(x))
162 self._rmproxy(d + '_undistorted')
163 self._rmproxy(os.path.join(absproxy, 'proxy_' + str(x) + '.avi'))
165 tc = ('free_run.blen_tc',
166 'interp_free_run.blen_tc',
167 'record_run.blen_tc')
170 self._rmproxy(os.path.join(absproxy, x))
172 # remove proxy per-clip directory
178 # remove [custom] proxy directory if empty
180 absdir = bpy.path.abspath(proxydir)
188 class CLIP_OT_set_viewport_background(Operator):
189 """Set current movie clip as a camera background in 3D viewport \
190 (works only when a 3D viewport is visible)"""
192 bl_idname = "clip.set_viewport_background"
193 bl_label = "Set as Background"
194 bl_options = {'UNDO', 'REGISTER'}
197 def poll(cls, context):
198 if context.space_data.type != 'CLIP_EDITOR':
201 sc = context.space_data
205 def _set_background(self, space_v3d, clip, user):
208 for x in space_v3d.background_images:
209 if x.source == 'MOVIE':
214 bgpic = space_v3d.background_images.add()
216 bgpic.source = 'MOVIE'
218 bgpic.clip_user.proxy_render_size = user.proxy_render_size
219 bgpic.clip_user.use_render_undistorted = user.use_render_undistorted
220 bgpic.use_camera_clip = False
221 bgpic.view_axis = 'CAMERA'
223 space_v3d.show_background_images = True
225 def execute(self, context):
226 sc = context.space_data
229 for area in context.window.screen.areas:
230 if area.type == 'VIEW_3D':
231 for space in area.spaces:
232 if space.type == 'VIEW_3D':
233 self._set_background(space, clip, sc.clip_user)
238 class CLIP_OT_constraint_to_fcurve(Operator):
239 """Create F-Curves for object which will copy \
240 object's movement caused by this constraint"""
242 bl_idname = "clip.constraint_to_fcurve"
243 bl_label = "Constraint to F-Curve"
244 bl_options = {'UNDO', 'REGISTER'}
246 def _bake_object(self, scene, ob):
251 frame_current = scene.frame_current
254 # Find constraint which would eb converting
255 # TODO: several camera solvers and track followers would fail,
256 # but can't think about eal workflow where it'll be useful
257 for x in ob.constraints:
258 if x.type in ('CAMERA_SOLVER', 'FOLLOW_TRACK'):
264 if con.type == 'FOLLOW_TRACK' and con.use_3d_position:
265 mat = ob.matrix_world.copy()
266 ob.constraints.remove(con)
267 ob.matrix_world = mat
271 # Get clip used for parenting
272 if con.use_active_clip:
273 clip = scene.active_clip
280 # Find start and end frames
281 for track in clip.tracking.tracks:
283 sfra = track.markers[0].frame
285 sfra = min(sfra, track.markers[0].frame)
288 efra = track.markers[-1].frame
290 efra = max(efra, track.markers[-1].frame)
292 if sfra is None or efra is None:
295 # Store object matrices
296 for x in range(sfra, efra + 1):
298 matrices.append(ob.matrix_world.copy())
300 ob.animation_data_create()
302 # Apply matrices on object and insert keyframes
304 for x in range(sfra, efra + 1):
306 ob.matrix_world = matrices[i]
308 ob.keyframe_insert("location")
310 if ob.rotation_mode == 'QUATERNION':
311 ob.keyframe_insert("rotation_quaternion")
313 ob.keyframe_insert("rotation_euler")
317 ob.constraints.remove(con)
319 scene.frame_set(frame_current)
321 def execute(self, context):
322 scene = context.scene
324 for ob in scene.objects:
326 self._bake_object(scene, ob)