@@ -1290,13 +1290,50 @@ def actionAddMarker_trigger(self, event):
1290
1290
marker .data = {"position" : position , "icon" : "blue.png" }
1291
1291
marker .save ()
1292
1292
1293
- def actionPreviousMarker_trigger (self , event ):
1294
- log .info ("actionPreviousMarker_trigger" )
1295
1293
1296
- # Calculate current position (in seconds)
1297
- fps = get_app ().project .get ("fps" )
1298
- fps_float = float (fps ["num" ]) / float (fps ["den" ])
1299
- current_position = (self .preview_thread .current_frame - 1 ) / fps_float
1294
+ def findAllMarkerPositions (self ):
1295
+ """Build and return a list of all seekable locations for the currently-selected timeline elements"""
1296
+
1297
+ def getTimelineObjectPositions (obj ):
1298
+ """ Add boundaries & all keyframes of a timeline object (clip, transition...) to all_marker_positions """
1299
+ positions = []
1300
+
1301
+ fps = get_app ().project .get ("fps" )
1302
+ fps_float = float (fps ["num" ]) / float (fps ["den" ])
1303
+
1304
+ clip_start_time = obj .data ["position" ]
1305
+ clip_orig_time = clip_start_time - obj .data ["start" ]
1306
+ clip_stop_time = clip_orig_time + obj .data ["end" ]
1307
+
1308
+ # add clip boundaries
1309
+ positions .append (clip_start_time )
1310
+ positions .append (clip_stop_time )
1311
+
1312
+ # add all keyframes
1313
+ for property in obj .data :
1314
+ try :
1315
+ for point in obj .data [property ]["Points" ] :
1316
+ keyframe_time = (point ["co" ]["X" ]- 1 )/ fps_float - obj .data ["start" ] + obj .data ["position" ]
1317
+ if keyframe_time > clip_start_time and keyframe_time < clip_stop_time :
1318
+ positions .append (keyframe_time )
1319
+ except (TypeError , KeyError ):
1320
+ pass
1321
+
1322
+
1323
+ # Add all Effect keyframes
1324
+ if "effects" in obj .data :
1325
+ for effect_data in obj .data ["effects" ]:
1326
+ for property in effect_data :
1327
+ try :
1328
+ for point in effect_data [property ]["Points" ]:
1329
+ keyframe_time = (point ["co" ]["X" ]- 1 )/ fps_float + clip_orig_time
1330
+ if keyframe_time > clip_start_time and keyframe_time < clip_stop_time :
1331
+ positions .append (keyframe_time )
1332
+ except (TypeError , KeyError ):
1333
+ pass
1334
+
1335
+ return positions
1336
+
1300
1337
all_marker_positions = []
1301
1338
1302
1339
# Get list of marker and important positions (like selected clip bounds)
@@ -1308,16 +1345,28 @@ def actionPreviousMarker_trigger(self, event):
1308
1345
# Get selected object
1309
1346
selected_clip = Clip .get (id = clip_id )
1310
1347
if selected_clip :
1311
- all_marker_positions .append (selected_clip .data ["position" ])
1312
- all_marker_positions .append (selected_clip .data ["position" ] + (selected_clip .data ["end" ] - selected_clip .data ["start" ]))
1348
+ all_marker_positions .extend (getTimelineObjectPositions (selected_clip ))
1313
1349
1314
1350
# Loop through selected transitions (and add key positions)
1315
1351
for tran_id in self .selected_transitions :
1316
1352
# Get selected object
1317
1353
selected_tran = Transition .get (id = tran_id )
1318
1354
if selected_tran :
1319
- all_marker_positions .append (selected_tran .data ["position" ])
1320
- all_marker_positions .append (selected_tran .data ["position" ] + (selected_tran .data ["end" ] - selected_tran .data ["start" ]))
1355
+ all_marker_positions .extend (getTimelineObjectPositions (selected_tran ))
1356
+
1357
+ # remove duplicates
1358
+ all_marker_positions = list (set (all_marker_positions ))
1359
+
1360
+ return all_marker_positions
1361
+
1362
+ def actionPreviousMarker_trigger (self , event ):
1363
+ log .info ("actionPreviousMarker_trigger" )
1364
+
1365
+ # Calculate current position (in seconds)
1366
+ fps = get_app ().project .get ("fps" )
1367
+ fps_float = float (fps ["num" ]) / float (fps ["den" ])
1368
+ current_position = (self .preview_thread .current_frame - 1 ) / fps_float
1369
+ all_marker_positions = self .findAllMarkerPositions ()
1321
1370
1322
1371
# Loop through all markers, and find the closest one to the left
1323
1372
closest_position = None
@@ -1349,27 +1398,7 @@ def actionNextMarker_trigger(self, event):
1349
1398
fps = get_app ().project .get ("fps" )
1350
1399
fps_float = float (fps ["num" ]) / float (fps ["den" ])
1351
1400
current_position = (self .preview_thread .current_frame - 1 ) / fps_float
1352
- all_marker_positions = []
1353
-
1354
- # Get list of marker and important positions (like selected clip bounds)
1355
- for marker in Marker .filter ():
1356
- all_marker_positions .append (marker .data ["position" ])
1357
-
1358
- # Loop through selected clips (and add key positions)
1359
- for clip_id in self .selected_clips :
1360
- # Get selected object
1361
- selected_clip = Clip .get (id = clip_id )
1362
- if selected_clip :
1363
- all_marker_positions .append (selected_clip .data ["position" ])
1364
- all_marker_positions .append (selected_clip .data ["position" ] + (selected_clip .data ["end" ] - selected_clip .data ["start" ]))
1365
-
1366
- # Loop through selected transitions (and add key positions)
1367
- for tran_id in self .selected_transitions :
1368
- # Get selected object
1369
- selected_tran = Transition .get (id = tran_id )
1370
- if selected_tran :
1371
- all_marker_positions .append (selected_tran .data ["position" ])
1372
- all_marker_positions .append (selected_tran .data ["position" ] + (selected_tran .data ["end" ] - selected_tran .data ["start" ]))
1401
+ all_marker_positions = self .findAllMarkerPositions ()
1373
1402
1374
1403
# Loop through all markers, and find the closest one to the right
1375
1404
closest_position = None
@@ -1590,6 +1619,31 @@ def keyPressEvent(self, event):
1590
1619
clip_ids = [c .id for c in intersecting_clips ]
1591
1620
trans_ids = [t .id for t in intersecting_trans ]
1592
1621
self .timeline .Slice_Triggered (2 , clip_ids , trans_ids , playhead_position )
1622
+ elif key .matches (self .getShortcutByName ("sliceSelectedKeepBothSides" )) == QKeySequence .ExactMatch :
1623
+ intersecting_clips = Clip .filter (intersect = playhead_position )
1624
+ intersecting_trans = Transition .filter (intersect = playhead_position )
1625
+ if intersecting_clips or intersecting_trans :
1626
+ # Get list of clip ids
1627
+ clip_ids = [c .id for c in intersecting_clips if c .id in self .selected_clips ]
1628
+ trans_ids = [t .id for t in intersecting_trans if t .id in self .selected_transitions ]
1629
+ self .timeline .Slice_Triggered (0 , clip_ids , trans_ids , playhead_position )
1630
+ elif key .matches (self .getShortcutByName ("sliceSelectedKeepLeftSide" )) == QKeySequence .ExactMatch :
1631
+ intersecting_clips = Clip .filter (intersect = playhead_position )
1632
+ intersecting_trans = Transition .filter (intersect = playhead_position )
1633
+ if intersecting_clips or intersecting_trans :
1634
+ # Get list of clip ids
1635
+ clip_ids = [c .id for c in intersecting_clips if c .id in self .selected_clips ]
1636
+ trans_ids = [t .id for t in intersecting_trans if t .id in self .selected_transitions ]
1637
+ self .timeline .Slice_Triggered (1 , clip_ids , trans_ids , playhead_position )
1638
+ elif key .matches (self .getShortcutByName ("sliceSelectedKeepRightSide" )) == QKeySequence .ExactMatch :
1639
+ intersecting_clips = Clip .filter (intersect = playhead_position )
1640
+ intersecting_trans = Transition .filter (intersect = playhead_position )
1641
+ if intersecting_clips or intersecting_trans :
1642
+ # Get list of ids that are also selected
1643
+ clip_ids = [c .id for c in intersecting_clips if c .id in self .selected_clips ]
1644
+ trans_ids = [t .id for t in intersecting_trans if t .id in self .selected_transitions ]
1645
+ self .timeline .Slice_Triggered (2 , clip_ids , trans_ids , playhead_position )
1646
+
1593
1647
elif key .matches (self .getShortcutByName ("copyAll" )) == QKeySequence .ExactMatch :
1594
1648
self .timeline .Copy_Triggered (- 1 , self .selected_clips , self .selected_transitions )
1595
1649
elif key .matches (self .getShortcutByName ("pasteAll" )) == QKeySequence .ExactMatch :
0 commit comments