From 238b139b102892f8c5625f7d1113876afa0a0be4 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Tue, 23 Dec 2025 09:39:28 +0100 Subject: [PATCH] Refine crop border dragging logic to improve responsiveness and accuracy Enhance the crop border dragging functionality in the VideoEditor class by implementing more precise logic for determining the side of the crop area when dragging outside its bounds. Adjustments to crop dimensions are now consistently based on the drag direction, ensuring a more intuitive user experience. This update also resets the drag state appropriately after the drag operation. --- croppa/main.py | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/croppa/main.py b/croppa/main.py index 5130fb7..334a4fe 100644 --- a/croppa/main.py +++ b/croppa/main.py @@ -157,6 +157,7 @@ class VideoEditor: self.crop_border_drag_start_pos = None # (screen_x, screen_y) when drag started self.crop_border_drag_start_rect = None # (x, y, w, h) in rotated coords when drag started self.crop_border_drag_inside = None # True if drag started inside crop area, False if outside + self.crop_border_drag_outside_side = None # 'left', 'right', 'top', 'bottom' if outside # Zoom settings self.zoom_factor = 1.0 @@ -3126,12 +3127,25 @@ class VideoEditor: # Check if cursor is inside crop area inside_crop = sx1 <= x <= sx2 and sy1 <= y <= sy2 + # Determine which side we're on if outside (for better contraction logic) + outside_side = None + if not inside_crop: + if x < sx1: + outside_side = 'left' + elif x > sx2: + outside_side = 'right' + elif y < sy1: + outside_side = 'top' + elif y > sy2: + outside_side = 'bottom' + if event == cv2.EVENT_LBUTTONDOWN: # Start dragging - record position and whether we're inside/outside self.crop_border_dragging = True self.crop_border_drag_start_pos = (x, y) self.crop_border_drag_start_rect = (eff_x, eff_y, eff_w, eff_h) self.crop_border_drag_inside = inside_crop + self.crop_border_drag_outside_side = outside_side elif event == cv2.EVENT_MOUSEMOVE and self.crop_border_dragging: if self.crop_border_drag_start_pos and self.crop_border_drag_start_rect and self.crop_border_drag_inside is not None: # Convert mouse movement from screen to rotated coords @@ -3173,17 +3187,21 @@ class VideoEditor: if new_x + new_w > rot_w: new_w = rot_w - new_x else: - # Outside crop: drag left -> adjust right border left (contract), drag right -> adjust right border right (expand) + # Outside crop: always contract based on drag direction + # Drag left -> contract right (move right border left) + # Drag right -> contract left (move left border right) if dx_r < 0: # Dragging left -> move right border left (contract right) new_w = max(self.CROP_MIN_SIZE, new_w + dx_r) if new_w < self.CROP_MIN_SIZE: new_w = self.CROP_MIN_SIZE else: - # Dragging right -> move right border right (expand right) - new_w = max(self.CROP_MIN_SIZE, new_w + dx_r) - if new_x + new_w > rot_w: - new_w = rot_w - new_x + # Dragging right -> move left border right (contract left) + new_x = max(0, new_x + dx_r) + new_w = new_w - dx_r + if new_w < self.CROP_MIN_SIZE: + new_w = self.CROP_MIN_SIZE + new_x = self.crop_border_drag_start_rect[0] + self.crop_border_drag_start_rect[2] - self.CROP_MIN_SIZE else: # Vertical movement if self.crop_border_drag_inside: @@ -3201,17 +3219,21 @@ class VideoEditor: if new_y + new_h > rot_h: new_h = rot_h - new_y else: - # Outside crop: drag up -> adjust bottom border up (contract), drag down -> adjust bottom border down (expand) + # Outside crop: always contract based on drag direction + # Drag up -> contract bottom (move bottom border up) + # Drag down -> contract top (move top border down) if dy_r < 0: # Dragging up -> move bottom border up (contract bottom) new_h = max(self.CROP_MIN_SIZE, new_h + dy_r) if new_h < self.CROP_MIN_SIZE: new_h = self.CROP_MIN_SIZE else: - # Dragging down -> move bottom border down (expand down) - new_h = max(self.CROP_MIN_SIZE, new_h + dy_r) - if new_y + new_h > rot_h: - new_h = rot_h - new_y + # Dragging down -> move top border down (contract top) + new_y = max(0, new_y + dy_r) + new_h = new_h - dy_r + if new_h < self.CROP_MIN_SIZE: + new_h = self.CROP_MIN_SIZE + new_y = self.crop_border_drag_start_rect[1] + self.crop_border_drag_start_rect[3] - self.CROP_MIN_SIZE # Convert back from rotated to original frame coords self._set_crop_from_rotated_rect((new_x, new_y, new_w, new_h)) @@ -3222,6 +3244,7 @@ class VideoEditor: self.crop_border_drag_start_pos = None self.crop_border_drag_start_rect = None self.crop_border_drag_inside = None + self.crop_border_drag_outside_side = None self.save_state() # Handle crop selection (Shift + click and drag)