mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-31 07:29:49 +00:00
Fix regression where interecting selections was not working
This commit is contained in:
parent
79b18fc242
commit
1e83173697
|
@ -1,7 +1,7 @@
|
||||||
shader_type canvas_item;
|
shader_type canvas_item;
|
||||||
render_mode unshaded;
|
render_mode unshaded;
|
||||||
|
|
||||||
uniform sampler2D selection : hint_default_black;
|
uniform sampler2D selection : filter_nearest, hint_default_black;
|
||||||
uniform vec4 color;
|
uniform vec4 color;
|
||||||
uniform float similarity_percent : hint_range(0.0, 100.0);
|
uniform float similarity_percent : hint_range(0.0, 100.0);
|
||||||
uniform int operation = 0; // 0 = add, 1 = subtract, 2 = intersect
|
uniform int operation = 0; // 0 = add, 1 = subtract, 2 = intersect
|
||||||
|
|
|
@ -92,8 +92,9 @@ func apply_selection(_position: Vector2i) -> void:
|
||||||
|
|
||||||
|
|
||||||
func set_ellipse(selection_map: SelectionMap, pos: Vector2i) -> void:
|
func set_ellipse(selection_map: SelectionMap, pos: Vector2i) -> void:
|
||||||
var project := Global.current_project
|
|
||||||
var bitmap_size := selection_map.get_size()
|
var bitmap_size := selection_map.get_size()
|
||||||
|
var previous_selection_map := SelectionMap.new() # Used for intersect
|
||||||
|
previous_selection_map.copy_from(selection_map)
|
||||||
if _intersect:
|
if _intersect:
|
||||||
selection_map.clear()
|
selection_map.clear()
|
||||||
var points := DrawingAlgos.get_ellipse_points_filled(Vector2.ZERO, _rect.size)
|
var points := DrawingAlgos.get_ellipse_points_filled(Vector2.ZERO, _rect.size)
|
||||||
|
@ -102,7 +103,7 @@ func set_ellipse(selection_map: SelectionMap, pos: Vector2i) -> void:
|
||||||
if fill_p.x < 0 or fill_p.y < 0 or fill_p.x >= bitmap_size.x or fill_p.y >= bitmap_size.y:
|
if fill_p.x < 0 or fill_p.y < 0 or fill_p.x >= bitmap_size.x or fill_p.y >= bitmap_size.y:
|
||||||
continue
|
continue
|
||||||
if _intersect:
|
if _intersect:
|
||||||
if project.selection_map.is_pixel_selected(fill_p):
|
if previous_selection_map.is_pixel_selected(fill_p):
|
||||||
selection_map.select_pixel(fill_p, true)
|
selection_map.select_pixel(fill_p, true)
|
||||||
else:
|
else:
|
||||||
selection_map.select_pixel(fill_p, !_subtract)
|
selection_map.select_pixel(fill_p, !_subtract)
|
||||||
|
|
|
@ -76,21 +76,26 @@ func apply_selection(_position) -> void:
|
||||||
super.apply_selection(_position)
|
super.apply_selection(_position)
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
var cleared := false
|
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:
|
if !_add and !_subtract and !_intersect:
|
||||||
cleared = true
|
cleared = true
|
||||||
Global.canvas.selection.clear_selection()
|
Global.canvas.selection.clear_selection()
|
||||||
if _draw_points.size() > 3:
|
if _draw_points.size() > 3:
|
||||||
if _intersect:
|
if _intersect:
|
||||||
project.selection_map.clear()
|
project.selection_map.clear()
|
||||||
lasso_selection(project.selection_map, _draw_points)
|
lasso_selection(project.selection_map, previous_selection_map, _draw_points)
|
||||||
|
|
||||||
# Handle mirroring
|
# Handle mirroring
|
||||||
if Tools.horizontal_mirror:
|
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:
|
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:
|
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()
|
Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect()
|
||||||
else:
|
else:
|
||||||
|
@ -102,14 +107,16 @@ func apply_selection(_position) -> void:
|
||||||
_last_position = Vector2.INF
|
_last_position = Vector2.INF
|
||||||
|
|
||||||
|
|
||||||
func lasso_selection(selection_map: SelectionMap, points: Array[Vector2i]) -> void:
|
func lasso_selection(
|
||||||
|
selection_map: SelectionMap, previous_selection_map: SelectionMap, points: Array[Vector2i]
|
||||||
|
) -> void:
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
var selection_size := selection_map.get_size()
|
var selection_size := selection_map.get_size()
|
||||||
for point in points:
|
for point in points:
|
||||||
if point.x < 0 or point.y < 0 or point.x >= selection_size.x or point.y >= selection_size.y:
|
if point.x < 0 or point.y < 0 or point.x >= selection_size.x or point.y >= selection_size.y:
|
||||||
continue
|
continue
|
||||||
if _intersect:
|
if _intersect:
|
||||||
if project.selection_map.is_pixel_selected(point):
|
if previous_selection_map.is_pixel_selected(point):
|
||||||
selection_map.select_pixel(point, true)
|
selection_map.select_pixel(point, true)
|
||||||
else:
|
else:
|
||||||
selection_map.select_pixel(point, !_subtract)
|
selection_map.select_pixel(point, !_subtract)
|
||||||
|
@ -122,7 +129,7 @@ func lasso_selection(selection_map: SelectionMap, points: Array[Vector2i]) -> vo
|
||||||
v.y = y
|
v.y = y
|
||||||
if Geometry2D.is_point_in_polygon(v, points):
|
if Geometry2D.is_point_in_polygon(v, points):
|
||||||
if _intersect:
|
if _intersect:
|
||||||
if project.selection_map.is_pixel_selected(v):
|
if previous_selection_map.is_pixel_selected(v):
|
||||||
selection_map.select_pixel(v, true)
|
selection_map.select_pixel(v, true)
|
||||||
else:
|
else:
|
||||||
selection_map.select_pixel(v, !_subtract)
|
selection_map.select_pixel(v, !_subtract)
|
||||||
|
|
|
@ -24,18 +24,19 @@ func apply_selection(pos: Vector2i) -> void:
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
if pos.x < 0 or pos.y < 0 or pos.x >= project.size.x or pos.y >= project.size.y:
|
if pos.x < 0 or pos.y < 0 or pos.x >= project.size.x or pos.y >= project.size.y:
|
||||||
return
|
return
|
||||||
|
var previous_selection_map := SelectionMap.new() # Used for intersect
|
||||||
|
previous_selection_map.copy_from(project.selection_map)
|
||||||
if !_add and !_subtract and !_intersect:
|
if !_add and !_subtract and !_intersect:
|
||||||
Global.canvas.selection.clear_selection()
|
Global.canvas.selection.clear_selection()
|
||||||
|
|
||||||
if _intersect:
|
if _intersect:
|
||||||
project.selection_map.clear()
|
project.selection_map.clear()
|
||||||
|
|
||||||
var cel_image := Image.new()
|
var cel_image := Image.new()
|
||||||
cel_image.copy_from(_get_draw_image())
|
cel_image.copy_from(_get_draw_image())
|
||||||
_flood_fill(pos, cel_image, project.selection_map)
|
_flood_fill(pos, cel_image, project.selection_map, previous_selection_map)
|
||||||
# Handle mirroring
|
# Handle mirroring
|
||||||
for mirror_pos in Tools.get_mirrored_positions(pos):
|
for mirror_pos in Tools.get_mirrored_positions(pos):
|
||||||
_flood_fill(mirror_pos, cel_image, project.selection_map)
|
_flood_fill(mirror_pos, cel_image, project.selection_map, previous_selection_map)
|
||||||
|
|
||||||
Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect()
|
Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect()
|
||||||
Global.canvas.selection.commit_undo("Select", undo_data)
|
Global.canvas.selection.commit_undo("Select", undo_data)
|
||||||
|
@ -119,7 +120,9 @@ func _check_flooded_segment(
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
func _flood_fill(pos: Vector2i, image: Image, selection_map: SelectionMap) -> void:
|
func _flood_fill(
|
||||||
|
pos: Vector2i, image: Image, selection_map: SelectionMap, previous_selection_map: SelectionMap
|
||||||
|
) -> void:
|
||||||
# implements the floodfill routine by Shawn Hargreaves
|
# implements the floodfill routine by Shawn Hargreaves
|
||||||
# from https://www1.udel.edu/CIS/software/dist/allegro-4.2.1/src/flood.c
|
# from https://www1.udel.edu/CIS/software/dist/allegro-4.2.1/src/flood.c
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
|
@ -130,7 +133,7 @@ func _flood_fill(pos: Vector2i, image: Image, selection_map: SelectionMap) -> vo
|
||||||
_compute_segments_for_image(pos, 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
|
# 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.
|
# 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(
|
func _compute_segments_for_image(
|
||||||
|
@ -162,18 +165,17 @@ func _compute_segments_for_image(
|
||||||
done = false
|
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
|
# short circuit for flat colors
|
||||||
for c in _allegro_image_segments.size():
|
for c in _allegro_image_segments.size():
|
||||||
var p := _allegro_image_segments[c]
|
var p := _allegro_image_segments[c]
|
||||||
for px in range(p.left_position, p.right_position + 1):
|
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
|
# We don't have to check again whether the point being processed is within the bounds
|
||||||
_set_bit(Vector2i(px, p.y), selection_map)
|
_set_bit(Vector2i(px, p.y), selection_map, previous_selection_map)
|
||||||
|
|
||||||
|
|
||||||
func _set_bit(p: Vector2i, selection_map: SelectionMap) -> void:
|
func _set_bit(p: Vector2i, selection_map: SelectionMap, prev_selection_map: SelectionMap) -> void:
|
||||||
var project := Global.current_project
|
|
||||||
if _intersect:
|
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:
|
else:
|
||||||
selection_map.select_pixel(p, !_subtract)
|
selection_map.select_pixel(p, !_subtract)
|
||||||
|
|
|
@ -104,6 +104,8 @@ func apply_selection(pos: Vector2i) -> void:
|
||||||
super.apply_selection(pos)
|
super.apply_selection(pos)
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
var cleared := false
|
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:
|
if !_add and !_subtract and !_intersect:
|
||||||
cleared = true
|
cleared = true
|
||||||
Global.canvas.selection.clear_selection()
|
Global.canvas.selection.clear_selection()
|
||||||
|
@ -111,15 +113,18 @@ func apply_selection(pos: Vector2i) -> void:
|
||||||
if _draw_points.size() >= 1:
|
if _draw_points.size() >= 1:
|
||||||
if _intersect:
|
if _intersect:
|
||||||
project.selection_map.clear()
|
project.selection_map.clear()
|
||||||
paint_selection(project.selection_map, _draw_points)
|
paint_selection(project.selection_map, previous_selection_map, _draw_points)
|
||||||
|
|
||||||
# Handle mirroring
|
# Handle mirroring
|
||||||
if Tools.horizontal_mirror:
|
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:
|
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:
|
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()
|
Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect()
|
||||||
else:
|
else:
|
||||||
|
@ -131,14 +136,15 @@ func apply_selection(pos: Vector2i) -> void:
|
||||||
_last_position = Vector2.INF
|
_last_position = Vector2.INF
|
||||||
|
|
||||||
|
|
||||||
func paint_selection(selection_map: SelectionMap, points: Array[Vector2i]) -> void:
|
func paint_selection(
|
||||||
var project := Global.current_project
|
selection_map: SelectionMap, previous_selection_map: SelectionMap, points: Array[Vector2i]
|
||||||
|
) -> void:
|
||||||
var selection_size := selection_map.get_size()
|
var selection_size := selection_map.get_size()
|
||||||
for point in points:
|
for point in points:
|
||||||
if point.x < 0 or point.y < 0 or point.x >= selection_size.x or point.y >= selection_size.y:
|
if point.x < 0 or point.y < 0 or point.x >= selection_size.x or point.y >= selection_size.y:
|
||||||
continue
|
continue
|
||||||
if _intersect:
|
if _intersect:
|
||||||
if project.selection_map.is_pixel_selected(point):
|
if previous_selection_map.is_pixel_selected(point):
|
||||||
selection_map.select_pixel(point, true)
|
selection_map.select_pixel(point, true)
|
||||||
else:
|
else:
|
||||||
selection_map.select_pixel(point, !_subtract)
|
selection_map.select_pixel(point, !_subtract)
|
||||||
|
|
|
@ -115,21 +115,26 @@ func apply_selection(pos: Vector2i) -> void:
|
||||||
return
|
return
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
var cleared := false
|
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:
|
if !_add and !_subtract and !_intersect:
|
||||||
cleared = true
|
cleared = true
|
||||||
Global.canvas.selection.clear_selection()
|
Global.canvas.selection.clear_selection()
|
||||||
if _draw_points.size() > 3:
|
if _draw_points.size() > 3:
|
||||||
if _intersect:
|
if _intersect:
|
||||||
project.selection_map.clear()
|
project.selection_map.clear()
|
||||||
lasso_selection(project.selection_map, _draw_points)
|
lasso_selection(project.selection_map, previous_selection_map, _draw_points)
|
||||||
|
|
||||||
# Handle mirroring
|
# Handle mirroring
|
||||||
if Tools.horizontal_mirror:
|
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:
|
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:
|
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()
|
Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect()
|
||||||
else:
|
else:
|
||||||
|
@ -143,14 +148,16 @@ func apply_selection(pos: Vector2i) -> void:
|
||||||
Global.canvas.previews.queue_redraw()
|
Global.canvas.previews.queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
func lasso_selection(selection_map: SelectionMap, points: Array[Vector2i]) -> void:
|
func lasso_selection(
|
||||||
|
selection_map: SelectionMap, previous_selection_map: SelectionMap, points: Array[Vector2i]
|
||||||
|
) -> void:
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
var selection_size := selection_map.get_size()
|
var selection_size := selection_map.get_size()
|
||||||
for point in points:
|
for point in points:
|
||||||
if point.x < 0 or point.y < 0 or point.x >= selection_size.x or point.y >= selection_size.y:
|
if point.x < 0 or point.y < 0 or point.x >= selection_size.x or point.y >= selection_size.y:
|
||||||
continue
|
continue
|
||||||
if _intersect:
|
if _intersect:
|
||||||
if project.selection_map.is_pixel_selected(point):
|
if previous_selection_map.is_pixel_selected(point):
|
||||||
selection_map.select_pixel(point, true)
|
selection_map.select_pixel(point, true)
|
||||||
else:
|
else:
|
||||||
selection_map.select_pixel(point, !_subtract)
|
selection_map.select_pixel(point, !_subtract)
|
||||||
|
@ -163,7 +170,7 @@ func lasso_selection(selection_map: SelectionMap, points: Array[Vector2i]) -> vo
|
||||||
v.y = y
|
v.y = y
|
||||||
if Geometry2D.is_point_in_polygon(v, points):
|
if Geometry2D.is_point_in_polygon(v, points):
|
||||||
if _intersect:
|
if _intersect:
|
||||||
if project.selection_map.is_pixel_selected(v):
|
if previous_selection_map.is_pixel_selected(v):
|
||||||
selection_map.select_pixel(v, true)
|
selection_map.select_pixel(v, true)
|
||||||
else:
|
else:
|
||||||
selection_map.select_pixel(v, !_subtract)
|
selection_map.select_pixel(v, !_subtract)
|
||||||
|
|
|
@ -421,14 +421,16 @@ func select_rect(rect: Rect2i, operation := SelectionOperation.ADD) -> void:
|
||||||
elif operation == SelectionOperation.SUBTRACT:
|
elif operation == SelectionOperation.SUBTRACT:
|
||||||
project.selection_map.fill_rect(rect, Color(0))
|
project.selection_map.fill_rect(rect, Color(0))
|
||||||
elif operation == SelectionOperation.INTERSECT:
|
elif operation == SelectionOperation.INTERSECT:
|
||||||
|
var previous_selection_map := SelectionMap.new()
|
||||||
|
previous_selection_map.copy_from(project.selection_map)
|
||||||
project.selection_map.clear()
|
project.selection_map.clear()
|
||||||
for x in range(rect.position.x, rect.end.x):
|
for x in range(rect.position.x, rect.end.x):
|
||||||
for y in range(rect.position.y, rect.end.y):
|
for y in range(rect.position.y, rect.end.y):
|
||||||
var pos := Vector2i(x, y)
|
var pos := Vector2i(x, y)
|
||||||
if !Rect2i(Vector2i.ZERO, project.selection_map.get_size()).has_point(pos):
|
if !Rect2i(Vector2i.ZERO, previous_selection_map.get_size()).has_point(pos):
|
||||||
continue
|
continue
|
||||||
project.selection_map.select_pixel(
|
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()
|
big_bounding_rectangle = project.selection_map.get_used_rect()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue