Expect input coordinates for the mesh projection function to be in world
[blender-addons-contrib.git] / sequencer_jumptocut.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
20 bl_info = {
21     "name": "Jump to Cut",
22     "author": "Carlos Padial",
23     "version": (5, 0, 2),
24     "blender": (2, 63, 0),
25     "category": "Sequencer",
26     "location": "Sequencer > UI > Jump to Cut",
27     "description": "Tool collection to help speed up editting and grade videos with blender",
28     "warning": "",
29     "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/Sequencer/Jump_to_cut",
30     "tracker_url": "https://developer.blender.org/T24279"}
31
32
33 import bpy
34
35 class Jumptocut(bpy.types.Panel):
36     bl_space_type = "SEQUENCE_EDITOR"
37     bl_region_type = "UI"
38     bl_label = "Jump to Cut"
39
40     def draw_header(self, context):
41         layout = self.layout
42         layout.label(text="", icon="NLA")
43
44     def draw(self, context):
45         layout = self.layout
46
47         row=layout.row()
48         split=row.split(percentage=0.5)
49         colL = split.column()
50         colR = split.column()
51         colL.operator("sequencer.jumpprev", icon="PLAY_REVERSE")
52         colR.operator("sequencer.jumpnext", icon='PLAY')
53
54         row=layout.row()
55         split=row.split()
56         colL = split.column()
57         colR = split.column()
58         colL.operator("sequencer.markprev", icon="MARKER_HLT")
59         colR.operator("sequencer.marknext", icon='MARKER_HLT')
60
61         row=layout.row()
62         split=row.split()
63         colL1 = split.column()
64         colL2 = split.column()
65         colL1.operator("sequencer.sourcein", icon="REW")
66         colL2.operator("sequencer.sourceout", icon='FF')
67
68
69         row=layout.row()
70         split=row.split()
71         colR1 = split.column()
72         colR1.operator("sequencer.setinout", icon="ARROW_LEFTRIGHT")
73         row=layout.row()
74         split=row.split(percentage=0.5)
75         colR1 = split.column()
76         colR1.operator("sequencer.triminout", icon="FULLSCREEN_EXIT")
77         colR2 = split.column()
78         colR2.operator("sequencer.setstartend", icon="SETTINGS")
79
80         row=layout.row()
81         split=row.split()
82         colR1 = split.column()
83         colR2 = split.column()
84         colR1.operator("sequencer.metacopy", icon="COPYDOWN")
85         colR2.operator("sequencer.metapaste", icon='PASTEDOWN')
86
87 #-----------------------------------------------------------------------------------------------------
88
89 class OBJECT_OT_Setinout(bpy.types.Operator):
90     bl_label = "Mark in & out to active strip"
91     bl_idname = "sequencer.setinout"
92     bl_description = "set IN and OUT markers to the active strip limits"
93
94     def invoke(self, context, event):
95         scene=bpy.context.scene
96         markers=scene.timeline_markers
97         seq=scene.sequence_editor
98         if seq:
99             strip= seq.active_strip
100             if strip != None:
101                 sin = strip.frame_start + strip.frame_offset_start
102                 sout = sin + strip.frame_final_duration
103                 if "IN" not in markers:
104                     mark=markers.new(name="IN")
105                     mark.frame=sin
106                 else:
107                     mark=markers["IN"]
108                     mark.frame=sin
109                 if "OUT" not in markers:
110                     mark= markers.new(name="OUT")
111                     mark.frame=sout
112                 else:
113                     mark=markers["OUT"]
114                     mark.frame=sout
115         return {'FINISHED'}
116
117
118 def triminout(strip,sin,sout):
119     start = strip.frame_start+strip.frame_offset_start
120     end = start+strip.frame_final_duration
121     if end > sin:
122         if start < sin:
123             strip.select_right_handle = False
124             strip.select_left_handle = True
125             bpy.ops.sequencer.snap(frame=sin)
126             strip.select_left_handle = False
127     if start < sout:
128         if end > sout:
129             strip.select_left_handle = False
130             strip.select_right_handle = True
131             bpy.ops.sequencer.snap(frame=sout)
132             strip.select_right_handle = False
133     return {'FINISHED'}
134
135
136 class OBJECT_OT_Triminout(bpy.types.Operator):
137     bl_label = "Trim to in & out"
138     bl_idname = "sequencer.triminout"
139     bl_description = "trim the selected strip to IN and OUT markers (if exists)"
140
141     def invoke(self, context, event):
142         scene=bpy.context.scene
143         markers=scene.timeline_markers
144         seq=scene.sequence_editor
145         if seq:
146             strip= seq.active_strip
147             if strip != None:
148                 if "IN" and "OUT" in markers:
149                     sin=markers["IN"].frame
150                     sout=markers["OUT"].frame
151                     triminout(strip,sin,sout)
152                 else:
153                     self.report({'WARNING'}, "there is no IN and OUT")
154             bpy.ops.sequencer.reload()
155         return {'FINISHED'}
156
157 def searchprev(j, list):
158     list.sort(reverse=True)
159     for i in list:
160         if i < j:
161             result = i
162             break
163     else: result = j
164     return result
165
166 def searchnext(j, list):
167     list.sort()
168     for i in list:
169         if i > j:
170             result = i
171             break
172     else: result = j
173     return result
174
175 def geteditpoints(seq):
176     #this create a list of editpoints including strips from
177     # inside metastrips. It reads only 1 level into the metastrip
178     editpoints = []
179     cliplist = []
180     metalist = []
181     if seq:
182         for i in seq.sequences:
183             if i.type == 'META':
184                 metalist.append(i)
185                 start = i.frame_start + i.frame_offset_start
186                 end = start + i.frame_final_duration
187                 editpoints.append(start)
188                 editpoints.append(end)
189             else:
190                 cliplist.append(i)
191         for i in metalist:
192             for j in i.sequences:
193                 cliplist.append(j)
194         for i in cliplist:
195             start = i.frame_start + i.frame_offset_start
196             end = start + i.frame_final_duration
197             editpoints.append(start)
198             editpoints.append(end)
199             #print(start," ",end)
200     return editpoints
201
202 #JUMP
203 class OBJECT_OT_Jumpprev(bpy.types.Operator):  #Operator jump previous edit point
204     bl_label = "Cut previous"
205     bl_idname = "sequencer.jumpprev"
206     bl_description = "jump to previous edit point"
207
208     editpoints = []
209
210     def invoke(self, context, event):
211         scene=bpy.context.scene
212         seq=scene.sequence_editor
213         editpoints = geteditpoints(seq)
214         bpy.context.scene.frame_current = searchprev(scene.frame_current, editpoints)
215         return {'FINISHED'}
216
217 class OBJECT_OT_Jumpnext(bpy.types.Operator):  #Operator jump next edit point
218     bl_label = "Cut next"
219     bl_idname = "sequencer.jumpnext"
220     bl_description = "jump to next edit point"
221
222     def invoke(self, context, event):
223         scene=bpy.context.scene
224         seq=scene.sequence_editor
225         editpoints = geteditpoints(seq)
226         bpy.context.scene.frame_current = searchnext(scene.frame_current, editpoints)
227         last = 0
228         for i in editpoints:
229             if i > last: last = i
230         if bpy.context.scene.frame_current == last:
231             bpy.context.scene.frame_current = last-1
232             self.report({'INFO'},'Last Frame')
233         return {'FINISHED'}
234
235 # MARKER
236 class OBJECT_OT_Markerprev(bpy.types.Operator):
237     bl_label = "Marker previous"
238     bl_idname = "sequencer.markprev"
239     bl_description = "jump to previous marker"
240
241     def invoke(self, context, event):
242         markerlist = []
243         scene= bpy.context.scene
244         markers = scene.timeline_markers
245         for i in markers: markerlist.append(i.frame)
246         bpy.context.scene.frame_current = searchprev(scene.frame_current, markerlist)
247         return {'FINISHED'}
248
249 class OBJECT_OT_Markernext(bpy.types.Operator):
250     bl_label = "Marker next"
251     bl_idname = "sequencer.marknext"
252     bl_description = "jump to next marker"
253
254     def invoke(self, context, event):
255         markerlist = []
256         scene= bpy.context.scene
257         markers = scene.timeline_markers
258         for i in markers: markerlist.append(i.frame)
259         bpy.context.scene.frame_current = searchnext(scene.frame_current, markerlist)
260         return {'FINISHED'}
261
262 # SOURCE IN OUT
263
264 class OBJECT_OT_Sourcein(bpy.types.Operator):  #Operator source in
265     bl_label = "Source IN"
266     bl_idname = "sequencer.sourcein"
267     bl_description = "add a marker named IN"
268
269     def invoke(self, context, event):
270         scene=bpy.context.scene
271         seq = scene.sequence_editor
272         markers=scene.timeline_markers
273         if "OUT" in markers:
274             sout=markers["OUT"]
275             if scene.frame_current <= sout.frame:
276                 if "IN" not in markers:
277                     sin=markers.new(name="IN")
278                     sin.frame=scene.frame_current
279                 else:
280                     sin=markers["IN"]
281                     sin.frame=scene.frame_current
282             #trying to set in after out
283             else:
284                 if "IN" not in markers:
285                     sin=markers.new(name="IN")
286                     sin.frame=sout.frame
287                 else:
288                     sin=markers["IN"]
289                     sin.frame=sout.frame
290                 self.report({'WARNING'},'IN after OUT')
291         else:
292             if "IN" not in markers:
293                 sin=markers.new(name="IN")
294                 sin.frame=scene.frame_current
295             else:
296                 sin=markers["IN"]
297                 sin.frame=scene.frame_current
298         if seq:
299             bpy.ops.sequencer.reload()
300         return {'FINISHED'}
301
302 class OBJECT_OT_Sourceout(bpy.types.Operator):  #Operator source out
303     bl_label = "Source OUT"
304     bl_idname = "sequencer.sourceout"
305     bl_description = "add a marker named OUT"
306
307     def invoke(self, context, event):
308         scene=bpy.context.scene
309         seq = scene.sequence_editor
310         markers=scene.timeline_markers
311         if "IN" in markers:
312             sin=markers["IN"]
313             if scene.frame_current >= sin.frame:
314                 if "OUT" not in markers:
315                     sout= markers.new(name="OUT")
316                     sout.frame=scene.frame_current
317                 else:
318                     sout=markers["OUT"]
319                     sout.frame=scene.frame_current
320             #trying to set out before in
321             else:
322                 if "OUT" not in markers:
323                     sout= markers.new(name="OUT")
324                     sout.frame = sin.frame
325                 else:
326                     sout=markers["OUT"]
327                     sout.frame = sin.frame
328                 self.report({'WARNING'}, "OUT before IN")
329         else:
330             sout= markers.new(name="OUT")
331             sout.frame=scene.frame_current
332         if seq:
333             bpy.ops.sequencer.reload()
334         return {'FINISHED'}
335
336
337
338 class OBJECT_OT_Setstartend(bpy.types.Operator):  #Operator set start & end
339     bl_label = "set Start & End"
340     bl_idname = "sequencer.setstartend"
341     bl_description = "set Start = In and End = Out"
342
343     def invoke(self, context, event):
344         scene=bpy.context.scene
345         seq = scene.sequence_editor
346         markers=scene.timeline_markers
347         if seq:
348             if "IN" and "OUT" in markers:
349                 sin=markers["IN"]
350                 sout=markers["OUT"]
351                 scene.frame_start = sin.frame
352                 scene.frame_end = sout.frame
353                 print("change")
354             else:
355                 self.report({'WARNING'}, "there is no IN and OUT")
356             bpy.ops.sequencer.reload()
357         return {'FINISHED'}
358
359
360 # COPY PASTE
361
362 class OBJECT_OT_Metacopy(bpy.types.Operator):  #Operator copy source in/out
363     bl_label = "Trim & Meta-Copy"
364     bl_idname = "sequencer.metacopy"
365     bl_description = "make meta from selected strips, trim it to in/out (if available) and copy it to clipboard"
366
367     def invoke(self, context, event):
368         # rehacer
369         scene=bpy.context.scene
370         seq = scene.sequence_editor
371         markers=scene.timeline_markers
372         strip1= seq.active_strip
373         if strip1 != None:
374             if "IN" and "OUT" in markers:
375                 sin=markers["IN"].frame
376                 sout=markers["OUT"].frame
377                 bpy.ops.sequencer.meta_make()
378                 strip2= seq.active_strip
379                 triminout(strip2,sin,sout)
380                 bpy.ops.sequencer.copy()
381                 bpy.ops.sequencer.meta_separate()
382                 self.report({'INFO'}, "META has been trimed and copied")
383             else:
384                 bpy.ops.sequencer.meta_make()
385                 bpy.ops.sequencer.copy()
386                 bpy.ops.sequencer.meta_separate()
387                 self.report({'WARNING'}, "No In & Out!! META has been copied")
388         else:
389             self.report({'ERROR'}, "No strip selected")
390         return {'FINISHED'}
391
392 class OBJECT_OT_Metapaste(bpy.types.Operator):  #Operator paste source in/out
393     bl_label = "Paste in current Frame"
394     bl_idname = "sequencer.metapaste"
395     bl_description = "paste source from clipboard to current frame"
396
397     def invoke(self, context, event):
398         # rehacer
399         scene=bpy.context.scene
400         bpy.ops.sequencer.paste()
401         bpy.ops.sequencer.snap(frame=scene.frame_current)
402         return {'FINISHED'}
403
404 # Registering / Unregister
405
406 def register():
407     bpy.utils.register_class(Jumptocut)
408     bpy.utils.register_class(OBJECT_OT_Jumpprev)
409     bpy.utils.register_class(OBJECT_OT_Jumpnext)
410     bpy.utils.register_class(OBJECT_OT_Markerprev)
411     bpy.utils.register_class(OBJECT_OT_Markernext)
412     bpy.utils.register_class(OBJECT_OT_Sourcein)
413     bpy.utils.register_class(OBJECT_OT_Sourceout)
414     bpy.utils.register_class(OBJECT_OT_Metacopy)
415     bpy.utils.register_class(OBJECT_OT_Metapaste)
416     bpy.utils.register_class(OBJECT_OT_Triminout)
417     bpy.utils.register_class(OBJECT_OT_Setinout)
418     bpy.utils.register_class(OBJECT_OT_Setstartend)
419
420 def unregister():
421     bpy.utils.unregister_class(Jumptocut)
422     bpy.utils.unregister_class(OBJECT_OT_Jumpprev)
423     bpy.utils.unregister_class(OBJECT_OT_Jumpnext)
424     bpy.utils.unregister_class(OBJECT_OT_Markerprev)
425     bpy.utils.unregister_class(OBJECT_OT_Markernext)
426     bpy.utils.unregister_class(OBJECT_OT_Sourcein)
427     bpy.utils.unregister_class(OBJECT_OT_Sourceout)
428     bpy.utils.unregister_class(OBJECT_OT_Metacopy)
429     bpy.utils.unregister_class(OBJECT_OT_Metapaste)
430     bpy.utils.unregister_class(OBJECT_OT_Triminout)
431     bpy.utils.unregister_class(OBJECT_OT_Setinout)
432     bpy.utils.unregister_class(OBJECT_OT_Setstartend)
433 if __name__ == "__main__":
434     register()