Skip to content

Added area fill mode where regions from the merging of all layers is filled #1258

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 43 additions & 4 deletions src/Tools/DesignTools/Bucket.gd
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ var _pattern: Patterns.Pattern
var _tolerance := 0.003
var _fill_area: int = FillArea.AREA
var _fill_with: int = FillWith.COLOR
var _fill_merged_area := false ## Fill regions from the merging of all layers
var _offset_x := 0
var _offset_y := 0
## Working array used as buffer for segments while flooding
var _allegro_flood_segments: Array[Segment]
## Results array per image while flooding
var _allegro_image_segments: Array[Segment]
## Used for _fill_merged_area = true
var _sample_masks: Dictionary[Frame, Image] = {}


class Segment:
Expand Down Expand Up @@ -59,8 +62,15 @@ func _on_FillAreaOptions_item_selected(index: int) -> void:
save_config()


func _on_merge_area_options_toggled(toggled_on: bool) -> void:
_fill_merged_area = toggled_on
update_config()
save_config()


func _select_fill_area_optionbutton() -> void:
$FillAreaOptions.selected = _fill_area
$MergeAreaOptions.visible = _fill_area == FillArea.AREA
$ToleranceSlider.visible = (_fill_area != FillArea.SELECTION)


Expand Down Expand Up @@ -103,10 +113,16 @@ func _on_PatternOffsetY_value_changed(value: float) -> void:

func get_config() -> Dictionary:
if !_pattern:
return {"fill_area": _fill_area, "fill_with": _fill_with, "tolerance": _tolerance}
return {
"fill_area": _fill_area,
"fill_merged_area": _fill_merged_area,
"fill_with": _fill_with,
"tolerance": _tolerance
}
return {
"pattern_index": _pattern.index,
"fill_area": _fill_area,
"fill_merged_area": _fill_merged_area,
"fill_with": _fill_with,
"tolerance": _tolerance,
"offset_x": _offset_x,
Expand All @@ -119,6 +135,7 @@ func set_config(config: Dictionary) -> void:
var index = config.get("pattern_index", _pattern.index)
_pattern = Global.patterns_popup.get_pattern(index)
_fill_area = config.get("fill_area", _fill_area)
_fill_merged_area = config.get("fill_merged_area", _fill_merged_area)
_fill_with = config.get("fill_with", _fill_with)
_tolerance = config.get("tolerance", _tolerance)
_offset_x = config.get("offset_x", _offset_x)
Expand All @@ -133,6 +150,7 @@ func update_config() -> void:
$FillPattern.visible = _fill_with == FillWith.PATTERN
$FillPattern/OffsetX.value = _offset_x
$FillPattern/OffsetY.value = _offset_y
$MergeAreaOptions.button_pressed = _fill_merged_area


func update_pattern() -> void:
Expand Down Expand Up @@ -163,6 +181,18 @@ func draw_start(pos: Vector2i) -> void:
return
if not Global.current_project.can_pixel_get_drawn(pos):
return
if _fill_merged_area and _fill_area == FillArea.AREA:
var project := Global.current_project
for frame_layer: Array in project.selected_cels:
if project.frames[frame_layer[0]].cels[frame_layer[1]] is PixelCel:
var frame := project.frames[frame_layer[0]]
if not _sample_masks.has(frame):
var mask := Image.create(
project.size.x, project.size.y, false, Image.FORMAT_RGBA8
)
mask.fill(Color(0, 0, 0, 0))
DrawingAlgos.blend_layers(mask, frame)
_sample_masks[frame] = mask
fill(pos)


Expand All @@ -183,6 +213,7 @@ func draw_end(pos: Vector2i) -> void:
super.draw_end(pos)
if _picking_color:
return
_sample_masks.clear()
commit_undo()


Expand Down Expand Up @@ -343,11 +374,14 @@ func _flood_fill(pos: Vector2i) -> void:
)
return

var images := _get_selected_draw_images()
for image in images:
var cels = _get_selected_draw_cels()
for cel: PixelCel in cels:
var image: ImageExtended = cel.image
if Tools.check_alpha_lock(image, pos):
continue
var color: Color = image.get_pixelv(pos)
if _fill_merged_area:
color = _sample_masks.get(cel.get_frame(project), cel.image).get_pixelv(pos)
if _fill_with == FillWith.COLOR or _pattern == null:
# end early if we are filling with the same color
if tool_slot.color.is_equal_approx(color):
Expand All @@ -360,7 +394,12 @@ func _flood_fill(pos: Vector2i) -> void:
# init flood data structures
_allegro_flood_segments = []
_allegro_image_segments = []
_compute_segments_for_image(pos, project, image, color)
_compute_segments_for_image(
pos,
project,
image if !_fill_merged_area else _sample_masks.get(cel.get_frame(project), cel.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.
_color_segments(image)
Expand Down
16 changes: 12 additions & 4 deletions src/Tools/DesignTools/Bucket.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,18 @@ mouse_default_cursor_shape = 2
selected = 0
item_count = 3
popup/item_0/text = "Similar area"
popup/item_0/id = 0
popup/item_1/text = "Similar colors"
popup/item_1/id = 1
popup/item_2/text = "Whole selection"
popup/item_2/id = 2

[node name="ToleranceSlider" type="TextureProgressBar" parent="." index="4"]
[node name="MergeAreaOptions" type="CheckBox" parent="." index="4"]
layout_mode = 2
text = "Fill regions from the merging of all layers"
autowrap_mode = 3

[node name="ToleranceSlider" type="TextureProgressBar" parent="." index="5"]
custom_minimum_size = Vector2(32, 24)
layout_mode = 2
focus_mode = 2
Expand All @@ -61,22 +67,23 @@ stretch_margin_bottom = 3
script = ExtResource("4_1pngp")
prefix = "Tolerance:"

[node name="FillWith" type="Label" parent="." index="5"]
[node name="FillWith" type="Label" parent="." index="6"]
layout_mode = 2
size_flags_horizontal = 3
text = "Fill with:"

[node name="FillWithOptions" type="OptionButton" parent="." index="6"]
[node name="FillWithOptions" type="OptionButton" parent="." index="7"]
layout_mode = 2
size_flags_horizontal = 3
mouse_default_cursor_shape = 2
selected = 0
item_count = 2
popup/item_0/text = "Selected color"
popup/item_0/id = 0
popup/item_1/text = "Pattern"
popup/item_1/id = 1

[node name="FillPattern" type="VBoxContainer" parent="." index="7"]
[node name="FillPattern" type="VBoxContainer" parent="." index="8"]
visible = false
layout_mode = 2
size_flags_horizontal = 3
Expand Down Expand Up @@ -109,6 +116,7 @@ layout_mode = 2
prefix = "Offset Y:"

[connection signal="item_selected" from="FillAreaOptions" to="." method="_on_FillAreaOptions_item_selected"]
[connection signal="toggled" from="MergeAreaOptions" to="." method="_on_merge_area_options_toggled"]
[connection signal="value_changed" from="ToleranceSlider" to="." method="_on_tolerance_slider_value_changed"]
[connection signal="item_selected" from="FillWithOptions" to="." method="_on_FillWithOptions_item_selected"]
[connection signal="pressed" from="FillPattern/Type" to="." method="_on_PatternType_pressed"]
Expand Down