Compare commits

...

2 Commits

View File

@@ -104,6 +104,9 @@ class VideoEditor:
# Cut points
self.cut_start_frame = None
self.cut_end_frame = None
# Marker looping state
self.looping_between_markers = False
# Display offset for panning when zoomed
self.display_offset = [0, 0]
@@ -320,7 +323,15 @@ class VideoEditor:
frames_to_advance = max(1, int(self.playback_speed))
new_frame = self.current_frame + frames_to_advance
if new_frame >= self.total_frames:
# Handle marker looping bounds
if self.looping_between_markers and self.cut_start_frame is not None and self.cut_end_frame is not None:
if new_frame >= self.cut_end_frame:
# Loop back to start marker
new_frame = self.cut_start_frame
self.current_frame = new_frame
return self.load_current_frame()
elif new_frame >= self.total_frames:
new_frame = 0 # Loop - this will require a seek
self.current_frame = new_frame
return self.load_current_frame()
@@ -348,8 +359,18 @@ class VideoEditor:
# Hit actual end of video
print(f"Reached actual end of video at frame {self.current_frame} (reported: {self.total_frames})")
self.total_frames = self.current_frame
self.current_frame = 0 # Loop back to start
if self.looping_between_markers and self.cut_start_frame is not None:
self.current_frame = self.cut_start_frame # Loop back to start marker
else:
self.current_frame = 0 # Loop back to start
return self.load_current_frame()
# Handle marker looping after successful frame load
if self.looping_between_markers and self.cut_start_frame is not None and self.cut_end_frame is not None:
if self.current_frame >= self.cut_end_frame:
self.current_frame = self.cut_start_frame
return self.load_current_frame()
return success
def apply_crop_zoom_and_rotation(self, frame):
@@ -1017,6 +1038,28 @@ class VideoEditor:
else:
self.crop_rect = None
def toggle_marker_looping(self):
"""Toggle looping between cut markers"""
# Check if both markers are set
if self.cut_start_frame is None or self.cut_end_frame is None:
print("Both markers must be set to enable looping. Use '1' and '2' to set markers.")
return False
if self.cut_start_frame >= self.cut_end_frame:
print("Invalid marker range - start frame must be before end frame")
return False
self.looping_between_markers = not self.looping_between_markers
if self.looping_between_markers:
print(f"Marker looping ENABLED: frames {self.cut_start_frame} - {self.cut_end_frame}")
# Jump to start marker when enabling
self.seek_to_frame(self.cut_start_frame)
else:
print("Marker looping DISABLED")
return True
def adjust_crop_size(self, direction: str, expand: bool, amount: int = None):
@@ -1303,6 +1346,7 @@ class VideoEditor:
print(" Ctrl+Scroll: Zoom in/out")
print(" 1: Set cut start point")
print(" 2: Set cut end point")
print(" T: Toggle loop between markers")
if len(self.video_files) > 1:
print(" N: Next video")
print(" n: Previous video")
@@ -1389,15 +1433,17 @@ class VideoEditor:
elif key == ord("2"):
self.cut_end_frame = self.current_frame
print(f"Set cut end at frame {self.current_frame}")
elif key == ord("n"):
elif key == ord("N"):
if len(self.video_files) > 1:
self.previous_video()
elif key == ord("N"):
elif key == ord("n"):
if len(self.video_files) > 1:
self.next_video()
elif key == 13: # Enter
output_name = self._get_next_edited_filename(self.video_path)
self.render_video(str(self.video_path.parent / output_name))
elif key == ord("t"):
self.toggle_marker_looping()
# Individual direction controls using shift combinations we can detect
elif key == ord("J"): # Shift+i - expand up