diff --git a/src/Tools/BaseTool.tscn b/src/Tools/BaseTool.tscn index 356f1b151..0ca256246 100644 --- a/src/Tools/BaseTool.tscn +++ b/src/Tools/BaseTool.tscn @@ -73,6 +73,7 @@ mouse_default_cursor_shape = 2 toggle_mode = true texture_normal = ExtResource( 5 ) texture_pressed = ExtResource( 4 ) + [connection signal="toggled" from="PixelPerfect" to="." method="_on_PixelPerfect_toggled"] [connection signal="toggled" from="Mirror/Horizontal" to="." method="_on_Horizontal_toggled"] [connection signal="toggled" from="Mirror/Vertical" to="." method="_on_Vertical_toggled"] diff --git a/src/Tools/SelectionTools/MagicWand.gd b/src/Tools/SelectionTools/MagicWand.gd index 30ccd7655..e0df62c36 100644 --- a/src/Tools/SelectionTools/MagicWand.gd +++ b/src/Tools/SelectionTools/MagicWand.gd @@ -3,11 +3,6 @@ extends SelectionTool func apply_selection(position : Vector2) -> void: var project : Project = Global.current_project - if position.x < 0 or position.y < 0: - return - if position.x > project.size.x - 1 or position.y > project.size.y - 1: - return - if !_add and !_subtract and !_intersect: Global.canvas.selection.clear_selection() @@ -19,36 +14,58 @@ func apply_selection(position : Vector2) -> void: var cel_image := Image.new() cel_image.copy_from(project.frames[project.current_frame].cels[project.current_layer].image) cel_image.lock() - var color := cel_image.get_pixelv(position) + flood_fill(position, cel_image, selection_bitmap_copy) + + # Handle mirroring + if tool_slot.horizontal_mirror: + var mirror_x := position + mirror_x.x = Global.current_project.x_symmetry_point - position.x + flood_fill(mirror_x, cel_image, selection_bitmap_copy) + if tool_slot.vertical_mirror: + var mirror_xy := mirror_x + mirror_xy.y = Global.current_project.y_symmetry_point - position.y + flood_fill(mirror_xy, cel_image, selection_bitmap_copy) + if tool_slot.vertical_mirror: + var mirror_y := position + mirror_y.y = Global.current_project.y_symmetry_point - position.y + flood_fill(mirror_y, cel_image, selection_bitmap_copy) + cel_image.unlock() + project.selection_bitmap = selection_bitmap_copy + Global.canvas.selection.big_bounding_rectangle = project.get_selection_rectangle(project.selection_bitmap) + Global.canvas.selection.commit_undo("Rectangle Select", undo_data) + + +func flood_fill(position : Vector2, image : Image, bitmap : BitMap) -> void: + var project : Project = Global.current_project + if position.x < 0 or position.y < 0: + return + if position.x > project.size.x - 1 or position.y > project.size.y - 1: + return + var color := image.get_pixelv(position) # Flood fill logic var processed := BitMap.new() - processed.create(cel_image.get_size()) + processed.create(image.get_size()) var q = [position] for n in q: if processed.get_bit(n): continue var west : Vector2 = n var east : Vector2 = n - while west.x >= 0 && cel_image.get_pixelv(west).is_equal_approx(color): + while west.x >= 0 && image.get_pixelv(west).is_equal_approx(color): west += Vector2.LEFT - while east.x < project.size.x && cel_image.get_pixelv(east).is_equal_approx(color): + while east.x < project.size.x && image.get_pixelv(east).is_equal_approx(color): east += Vector2.RIGHT for px in range(west.x + 1, east.x): var p := Vector2(px, n.y) if _intersect: - selection_bitmap_copy.set_bit(p, project.selection_bitmap.get_bit(p)) + bitmap.set_bit(p, project.selection_bitmap.get_bit(p)) else: - selection_bitmap_copy.set_bit(p, !_subtract) + bitmap.set_bit(p, !_subtract) processed.set_bit(p, true) var north := p + Vector2.UP var south := p + Vector2.DOWN - if north.y >= 0 && cel_image.get_pixelv(north).is_equal_approx(color): + if north.y >= 0 && image.get_pixelv(north).is_equal_approx(color): q.append(north) - if south.y < project.size.y && cel_image.get_pixelv(south).is_equal_approx(color): + if south.y < project.size.y && image.get_pixelv(south).is_equal_approx(color): q.append(south) - - cel_image.unlock() - project.selection_bitmap = selection_bitmap_copy - Global.canvas.selection.big_bounding_rectangle = project.get_selection_rectangle(project.selection_bitmap) - Global.canvas.selection.commit_undo("Rectangle Select", undo_data) diff --git a/src/Tools/SelectionTools/RectSelect.gd b/src/Tools/SelectionTools/RectSelect.gd index 0ca0a9ca5..4323bdfc2 100644 --- a/src/Tools/SelectionTools/RectSelect.gd +++ b/src/Tools/SelectionTools/RectSelect.gd @@ -53,6 +53,23 @@ func draw_preview() -> void: _scale.x = -1 canvas.draw_set_transform(_position, canvas.rotation, _scale) canvas.draw_rect(_rect, Color.black, false) + + # Handle mirroring + if tool_slot.horizontal_mirror: + var mirror_x_rect := _rect + mirror_x_rect.position.x = Global.current_project.x_symmetry_point - _rect.position.x + mirror_x_rect.end.x = Global.current_project.x_symmetry_point - _rect.end.x + canvas.draw_rect(mirror_x_rect, Color.black, false) + if tool_slot.vertical_mirror: + var mirror_xy_rect := mirror_x_rect + mirror_xy_rect.position.y = Global.current_project.y_symmetry_point - _rect.position.y + mirror_xy_rect.end.y = Global.current_project.y_symmetry_point - _rect.end.y + canvas.draw_rect(mirror_xy_rect, Color.black, false) + if tool_slot.vertical_mirror: + var mirror_y_rect := _rect + mirror_y_rect.position.y = Global.current_project.y_symmetry_point - _rect.position.y + mirror_y_rect.end.y = Global.current_project.y_symmetry_point - _rect.end.y + canvas.draw_rect(mirror_y_rect, Color.black, false) canvas.draw_set_transform(canvas.position, canvas.rotation, canvas.scale) @@ -68,6 +85,24 @@ func apply_selection(_position) -> void: elif _intersect: operation = 2 Global.canvas.selection.select_rect(_rect, operation) + + # Handle mirroring + if tool_slot.horizontal_mirror: + var mirror_x_rect := _rect + mirror_x_rect.position.x = Global.current_project.x_symmetry_point - _rect.position.x + mirror_x_rect.end.x = Global.current_project.x_symmetry_point - _rect.end.x + Global.canvas.selection.select_rect(mirror_x_rect.abs(), operation) + if tool_slot.vertical_mirror: + var mirror_xy_rect := mirror_x_rect + mirror_xy_rect.position.y = Global.current_project.y_symmetry_point - _rect.position.y + mirror_xy_rect.end.y = Global.current_project.y_symmetry_point - _rect.end.y + Global.canvas.selection.select_rect(mirror_xy_rect.abs(), operation) + if tool_slot.vertical_mirror: + var mirror_y_rect := _rect + mirror_y_rect.position.y = Global.current_project.y_symmetry_point - _rect.position.y + mirror_y_rect.end.y = Global.current_project.y_symmetry_point - _rect.end.y + Global.canvas.selection.select_rect(mirror_y_rect.abs(), operation) + Global.canvas.selection.commit_undo("Rectangle Select", undo_data) diff --git a/src/Tools/SelectionTools/SelectionTool.tscn b/src/Tools/SelectionTools/SelectionTool.tscn index ef69f5008..45a9e1a28 100644 --- a/src/Tools/SelectionTools/SelectionTool.tscn +++ b/src/Tools/SelectionTools/SelectionTool.tscn @@ -118,14 +118,12 @@ allow_greater = true visible = false [node name="EmptySpacer" parent="." index="8"] -visible = false -margin_top = 18.0 -margin_bottom = 30.0 +margin_top = 166.0 +margin_bottom = 178.0 [node name="Mirror" parent="." index="9"] -visible = false -margin_top = 18.0 -margin_bottom = 35.0 +margin_top = 182.0 +margin_bottom = 199.0 [connection signal="value_changed" from="XContainer/XSpinBox" to="." method="_on_XSpinBox_value_changed"] [connection signal="value_changed" from="YContainer/YSpinBox" to="." method="_on_YSpinBox_value_changed"]