diff --git a/src/Tools/SelectionTools/EllipseSelect.gd b/src/Tools/SelectionTools/EllipseSelect.gd index 2895febc7..cd5f097b4 100644 --- a/src/Tools/SelectionTools/EllipseSelect.gd +++ b/src/Tools/SelectionTools/EllipseSelect.gd @@ -52,7 +52,7 @@ func draw_preview() -> void: var canvas: Node2D = Global.canvas.previews var position := canvas.position var scale := canvas.scale - var temp_rect = _rect + var temp_rect := _rect if Global.mirror_view: position.x = position.x + Global.current_project.size.x temp_rect.position.x = Global.current_project.size.x - temp_rect.position.x @@ -113,8 +113,9 @@ func apply_selection(_position: Vector2) -> void: func set_ellipse(selection_map: SelectionMap, position: Vector2) -> void: - var project: Project = Global.current_project var bitmap_size: Vector2 = selection_map.get_size() + var previous_selection_map := SelectionMap.new() # Used for intersect + previous_selection_map.copy_from(selection_map) if _intersect: selection_map.clear() var points := _get_shape_points_filled(_rect.size) @@ -123,7 +124,7 @@ func set_ellipse(selection_map: SelectionMap, position: Vector2) -> void: if pos.x < 0 or pos.y < 0 or pos.x >= bitmap_size.x or pos.y >= bitmap_size.y: continue if _intersect: - if project.selection_map.is_pixel_selected(pos): + if previous_selection_map.is_pixel_selected(pos): selection_map.select_pixel(pos, true) else: selection_map.select_pixel(pos, !_subtract) diff --git a/src/Tools/SelectionTools/Lasso.gd b/src/Tools/SelectionTools/Lasso.gd index 38908ae49..180a6e0ee 100644 --- a/src/Tools/SelectionTools/Lasso.gd +++ b/src/Tools/SelectionTools/Lasso.gd @@ -77,21 +77,26 @@ func apply_selection(_position) -> void: .apply_selection(_position) var project: Project = Global.current_project var cleared := false + var previous_selection_map := SelectionMap.new() # Used for intersect + previous_selection_map.copy_from(project.selection_map) if !_add and !_subtract and !_intersect: cleared = true Global.canvas.selection.clear_selection() if _draw_points.size() > 3: if _intersect: project.selection_map.clear() - lasso_selection(project.selection_map, _draw_points) + lasso_selection(project.selection_map, previous_selection_map, _draw_points) # Handle mirroring if Tools.horizontal_mirror: - lasso_selection(project.selection_map, mirror_array(_draw_points, true, false)) + var mirror_x := mirror_array(_draw_points, true, false) + lasso_selection(project.selection_map, previous_selection_map, mirror_x) if Tools.vertical_mirror: - lasso_selection(project.selection_map, mirror_array(_draw_points, true, true)) + var mirror_xy := mirror_array(_draw_points, true, true) + lasso_selection(project.selection_map, previous_selection_map, mirror_xy) if Tools.vertical_mirror: - lasso_selection(project.selection_map, mirror_array(_draw_points, false, true)) + var mirror_y := mirror_array(_draw_points, false, true) + lasso_selection(project.selection_map, previous_selection_map, mirror_y) Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect() else: @@ -103,14 +108,16 @@ func apply_selection(_position) -> void: _last_position = Vector2.INF -func lasso_selection(selection_map: SelectionMap, points: PoolVector2Array) -> void: +func lasso_selection( + selection_map: SelectionMap, previous_selection_map: SelectionMap, points: PoolVector2Array +) -> void: var project: Project = Global.current_project var size := selection_map.get_size() for point in points: if point.x < 0 or point.y < 0 or point.x >= size.x or point.y >= size.y: continue if _intersect: - if project.selection_map.is_pixel_selected(point): + if previous_selection_map.is_pixel_selected(point): selection_map.select_pixel(point, true) else: selection_map.select_pixel(point, !_subtract) @@ -123,7 +130,7 @@ func lasso_selection(selection_map: SelectionMap, points: PoolVector2Array) -> v v.y = y if Geometry.is_point_in_polygon(v, points): if _intersect: - if project.selection_map.is_pixel_selected(v): + if previous_selection_map.is_pixel_selected(v): selection_map.select_pixel(v, true) else: selection_map.select_pixel(v, !_subtract) diff --git a/src/Tools/SelectionTools/MagicWand.gd b/src/Tools/SelectionTools/MagicWand.gd index 4f8e0ebc1..be89b4048 100644 --- a/src/Tools/SelectionTools/MagicWand.gd +++ b/src/Tools/SelectionTools/MagicWand.gd @@ -12,30 +12,31 @@ func apply_selection(position: Vector2) -> void: var size: Vector2 = project.size if position.x < 0 or position.y < 0 or position.x >= size.x or position.y >= size.y: return + var previous_selection_map := SelectionMap.new() # Used for intersect + previous_selection_map.copy_from(project.selection_map) if !_add and !_subtract and !_intersect: Global.canvas.selection.clear_selection() - if _intersect: project.selection_map.clear() var cel_image := Image.new() cel_image.copy_from(_get_draw_image()) cel_image.lock() - _flood_fill(position, cel_image, project.selection_map) + _flood_fill(position, cel_image, project.selection_map, previous_selection_map) # Handle mirroring if Tools.horizontal_mirror: var mirror_x := position mirror_x.x = Global.current_project.x_symmetry_point - position.x - _flood_fill(mirror_x, cel_image, project.selection_map) + _flood_fill(mirror_x, cel_image, project.selection_map, previous_selection_map) if Tools.vertical_mirror: var mirror_xy := mirror_x mirror_xy.y = Global.current_project.y_symmetry_point - position.y - _flood_fill(mirror_xy, cel_image, project.selection_map) + _flood_fill(mirror_xy, cel_image, project.selection_map, previous_selection_map) if Tools.vertical_mirror: var mirror_y := position mirror_y.y = Global.current_project.y_symmetry_point - position.y - _flood_fill(mirror_y, cel_image, project.selection_map) + _flood_fill(mirror_y, cel_image, project.selection_map, previous_selection_map) cel_image.unlock() Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect() Global.canvas.selection.commit_undo("Select", undo_data) @@ -127,18 +128,20 @@ func _check_flooded_segment( return ret -func _flood_fill(position: Vector2, image: Image, selection_map: SelectionMap) -> void: +func _flood_fill( + pos: Vector2, image: Image, selection_map: SelectionMap, previous_selection_map: SelectionMap +) -> void: # implements the floodfill routine by Shawn Hargreaves # from https://www1.udel.edu/CIS/software/dist/allegro-4.2.1/src/flood.c var project: Project = Global.current_project - var color: Color = image.get_pixelv(position) + var color: Color = image.get_pixelv(pos) # init flood data structures _allegro_flood_segments = [] _allegro_image_segments = [] - _compute_segments_for_image(position, project, image, color) + _compute_segments_for_image(pos, project, image, color) # now actually color the image: since we have already checked a few things for the points # we'll process here, we're going to skip a bunch of safety checks to speed things up. - _select_segments(selection_map) + _select_segments(selection_map, previous_selection_map) func _compute_segments_for_image( @@ -170,18 +173,17 @@ func _compute_segments_for_image( done = false -func _select_segments(selection_map: SelectionMap) -> void: +func _select_segments(selection_map: SelectionMap, previous_selection_map: SelectionMap) -> void: # short circuit for flat colors for c in _allegro_image_segments.size(): var p = _allegro_image_segments[c] for px in range(p.left_position, p.right_position + 1): # We don't have to check again whether the point being processed is within the bounds - _set_bit(Vector2(px, p.y), selection_map) + _set_bit(Vector2(px, p.y), selection_map, previous_selection_map) -func _set_bit(p: Vector2, selection_map: SelectionMap) -> void: - var project: Project = Global.current_project +func _set_bit(p: Vector2, selection_map: SelectionMap, prev_selection_map: SelectionMap) -> void: if _intersect: - selection_map.select_pixel(p, project.selection_map.is_pixel_selected(p)) + selection_map.select_pixel(p, prev_selection_map.is_pixel_selected(p)) else: selection_map.select_pixel(p, !_subtract) diff --git a/src/Tools/SelectionTools/PaintSelect.gd b/src/Tools/SelectionTools/PaintSelect.gd index a889169c6..47d7de505 100644 --- a/src/Tools/SelectionTools/PaintSelect.gd +++ b/src/Tools/SelectionTools/PaintSelect.gd @@ -105,6 +105,8 @@ func apply_selection(_position) -> void: .apply_selection(_position) var project: Project = Global.current_project var cleared := false + var previous_selection_map := SelectionMap.new() # Used for intersect + previous_selection_map.copy_from(project.selection_map) if !_add and !_subtract and !_intersect: cleared = true Global.canvas.selection.clear_selection() @@ -112,15 +114,18 @@ func apply_selection(_position) -> void: if _draw_points.size() >= 1: if _intersect: project.selection_map.clear() - paint_selection(project.selection_map, _draw_points) + paint_selection(project.selection_map, previous_selection_map, _draw_points) # Handle mirroring if Tools.horizontal_mirror: - paint_selection(project.selection_map, mirror_array(_draw_points, true, false)) + var mirror_x := mirror_array(_draw_points, true, false) + paint_selection(project.selection_map, previous_selection_map, mirror_x) if Tools.vertical_mirror: - paint_selection(project.selection_map, mirror_array(_draw_points, true, true)) + var mirror_xy := mirror_array(_draw_points, true, true) + paint_selection(project.selection_map, previous_selection_map, mirror_xy) if Tools.vertical_mirror: - paint_selection(project.selection_map, mirror_array(_draw_points, false, true)) + var mirror_y := mirror_array(_draw_points, false, true) + paint_selection(project.selection_map, previous_selection_map, mirror_y) Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect() else: @@ -132,14 +137,15 @@ func apply_selection(_position) -> void: _last_position = Vector2.INF -func paint_selection(selection_map: SelectionMap, points: PoolVector2Array) -> void: - var project: Project = Global.current_project +func paint_selection( + selection_map: SelectionMap, previous_selection_map: SelectionMap, points: PoolVector2Array +) -> void: var size := selection_map.get_size() for point in points: if point.x < 0 or point.y < 0 or point.x >= size.x or point.y >= size.y: continue if _intersect: - if project.selection_map.is_pixel_selected(point): + if previous_selection_map.is_pixel_selected(point): selection_map.select_pixel(point, true) else: selection_map.select_pixel(point, !_subtract) diff --git a/src/Tools/SelectionTools/PolygonSelect.gd b/src/Tools/SelectionTools/PolygonSelect.gd index ac1db8123..b45f0b155 100644 --- a/src/Tools/SelectionTools/PolygonSelect.gd +++ b/src/Tools/SelectionTools/PolygonSelect.gd @@ -115,21 +115,26 @@ func apply_selection(_position) -> void: return var project: Project = Global.current_project var cleared := false + var previous_selection_map := SelectionMap.new() # Used for intersect + previous_selection_map.copy_from(project.selection_map) if !_add and !_subtract and !_intersect: cleared = true Global.canvas.selection.clear_selection() if _draw_points.size() > 3: if _intersect: project.selection_map.clear() - lasso_selection(project.selection_map, _draw_points) + lasso_selection(project.selection_map, previous_selection_map, _draw_points) # Handle mirroring if Tools.horizontal_mirror: - lasso_selection(project.selection_map, mirror_array(_draw_points, true, false)) + var mirror_x := mirror_array(_draw_points, true, false) + lasso_selection(project.selection_map, previous_selection_map, mirror_x) if Tools.vertical_mirror: - lasso_selection(project.selection_map, mirror_array(_draw_points, true, true)) + var mirror_xy := mirror_array(_draw_points, true, true) + lasso_selection(project.selection_map, previous_selection_map, mirror_xy) if Tools.vertical_mirror: - lasso_selection(project.selection_map, mirror_array(_draw_points, false, true)) + var mirror_y := mirror_array(_draw_points, false, true) + lasso_selection(project.selection_map, previous_selection_map, mirror_y) Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect() else: @@ -143,14 +148,16 @@ func apply_selection(_position) -> void: Global.canvas.previews.update() -func lasso_selection(selection_map: SelectionMap, points: PoolVector2Array) -> void: +func lasso_selection( + selection_map: SelectionMap, previous_selection_map: SelectionMap, points: PoolVector2Array +) -> void: var project: Project = Global.current_project var size := selection_map.get_size() for point in points: if point.x < 0 or point.y < 0 or point.x >= size.x or point.y >= size.y: continue if _intersect: - if project.selection_map.is_pixel_selected(point): + if previous_selection_map.is_pixel_selected(point): selection_map.select_pixel(point, true) else: selection_map.select_pixel(point, !_subtract) @@ -163,7 +170,7 @@ func lasso_selection(selection_map: SelectionMap, points: PoolVector2Array) -> v v.y = y if Geometry.is_point_in_polygon(v, points): if _intersect: - if project.selection_map.is_pixel_selected(v): + if previous_selection_map.is_pixel_selected(v): selection_map.select_pixel(v, true) else: selection_map.select_pixel(v, !_subtract) diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index eaa04ca1d..9a1816a3e 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -451,14 +451,16 @@ func select_rect(rect: Rect2, operation: int = SelectionOperation.ADD) -> void: elif operation == SelectionOperation.SUBTRACT: project.selection_map.fill_rect(rect, Color(0)) elif operation == SelectionOperation.INTERSECT: + var previous_selection_map := SelectionMap.new() # Used for intersect + previous_selection_map.copy_from(project.selection_map) project.selection_map.clear() for x in range(rect.position.x, rect.end.x): for y in range(rect.position.y, rect.end.y): var pos := Vector2(x, y) - if !Rect2(Vector2.ZERO, project.selection_map.get_size()).has_point(pos): + if !Rect2(Vector2.ZERO, previous_selection_map.get_size()).has_point(pos): continue project.selection_map.select_pixel( - pos, project.selection_map.is_pixel_selected(pos) + pos, previous_selection_map.is_pixel_selected(pos) ) big_bounding_rectangle = project.selection_map.get_used_rect()