mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-18 17:19:50 +00:00
Pattern filling - Partially addresses #130
If the user chooses a brush that is not the pixel or a circle brush and uses the bucket tool, the brush image is used as a pattern that fills the area.
This commit is contained in:
parent
61c4ea7aa1
commit
e072b95727
|
@ -10,12 +10,13 @@ func _on_BrushButton_pressed() -> void:
|
|||
if Input.is_action_just_released("middle_mouse"):
|
||||
_on_DeleteButton_pressed()
|
||||
return
|
||||
|
||||
# Change left brush
|
||||
if Global.brush_type_window_position == "left":
|
||||
Global.current_left_brush_type = brush_type
|
||||
Global.custom_left_brush_index = custom_brush_index
|
||||
if custom_brush_index > -1: # Custom brush
|
||||
if Global.current_left_tool == "Pencil":
|
||||
if Global.current_left_tool == "Pencil" or Global.current_left_tool == "Bucket":
|
||||
Global.left_color_interpolation_container.visible = true
|
||||
# if hint_tooltip == "":
|
||||
# Global.left_brush_type_label.text = tr("Custom brush")
|
||||
|
@ -37,7 +38,7 @@ func _on_BrushButton_pressed() -> void:
|
|||
Global.current_right_brush_type = brush_type
|
||||
Global.custom_right_brush_index = custom_brush_index
|
||||
if custom_brush_index > -1:
|
||||
if Global.current_right_tool == "Pencil":
|
||||
if Global.current_right_tool == "Pencil" or Global.current_right_tool == "Bucket":
|
||||
Global.right_color_interpolation_container.visible = true
|
||||
# if hint_tooltip == "":
|
||||
# Global.right_brush_type_label.text = tr("Custom brush")
|
||||
|
|
|
@ -333,6 +333,20 @@ func _input(event : InputEvent) -> void:
|
|||
pencil_and_eraser(sprite, mouse_pos, Color(0, 0, 0, 0), current_mouse_button, current_action)
|
||||
"Bucket":
|
||||
if can_handle:
|
||||
var brush_type = Global.Brush_Types.PIXEL
|
||||
var custom_brush_image : Image
|
||||
var is_custom_brush := false
|
||||
if current_mouse_button == "left_mouse":
|
||||
brush_type = Global.current_left_brush_type
|
||||
is_custom_brush = brush_type == Global.Brush_Types.FILE or brush_type == Global.Brush_Types.CUSTOM or brush_type == Global.Brush_Types.RANDOM_FILE
|
||||
if is_custom_brush:
|
||||
custom_brush_image = Global.custom_left_brush_image
|
||||
elif current_mouse_button == "right_mouse":
|
||||
brush_type = Global.current_right_brush_type
|
||||
is_custom_brush = brush_type == Global.Brush_Types.FILE or brush_type == Global.Brush_Types.CUSTOM or brush_type == Global.Brush_Types.RANDOM_FILE
|
||||
if is_custom_brush:
|
||||
custom_brush_image = Global.custom_right_brush_image
|
||||
|
||||
if fill_area == 0: # Paint the specific area of the same color
|
||||
var horizontal_mirror := false
|
||||
var vertical_mirror := false
|
||||
|
@ -345,6 +359,18 @@ func _input(event : InputEvent) -> void:
|
|||
horizontal_mirror = Global.right_horizontal_mirror
|
||||
vertical_mirror = Global.right_vertical_mirror
|
||||
|
||||
if is_custom_brush: # Pattern fill
|
||||
pattern_fill(sprite, mouse_pos, custom_brush_image, sprite.get_pixelv(mouse_pos))
|
||||
if horizontal_mirror:
|
||||
var pos := Vector2(mirror_x, mouse_pos.y)
|
||||
pattern_fill(sprite, pos, custom_brush_image, sprite.get_pixelv(mouse_pos))
|
||||
if vertical_mirror:
|
||||
var pos := Vector2(mouse_pos.x, mirror_y)
|
||||
pattern_fill(sprite, pos, custom_brush_image, sprite.get_pixelv(mouse_pos))
|
||||
if horizontal_mirror && vertical_mirror:
|
||||
var pos := Vector2(mirror_x, mirror_y)
|
||||
pattern_fill(sprite, pos, custom_brush_image, sprite.get_pixelv(mouse_pos))
|
||||
else: # Flood fill
|
||||
flood_fill(sprite, mouse_pos, sprite.get_pixelv(mouse_pos), current_color)
|
||||
if horizontal_mirror:
|
||||
var pos := Vector2(mirror_x, mouse_pos.y)
|
||||
|
@ -362,6 +388,15 @@ func _input(event : InputEvent) -> void:
|
|||
for yy in range(north_limit, south_limit):
|
||||
var c : Color = sprite.get_pixel(xx, yy)
|
||||
if c == pixel_color:
|
||||
if is_custom_brush: # Pattern fill
|
||||
custom_brush_image.lock()
|
||||
var pattern_size := custom_brush_image.get_size()
|
||||
var xxx : int = int(xx) % int(pattern_size.x)
|
||||
var yyy : int = int(yy) % int(pattern_size.y)
|
||||
var pattern_color : Color = custom_brush_image.get_pixel(xxx, yyy)
|
||||
sprite.set_pixel(xx, yy, pattern_color)
|
||||
custom_brush_image.unlock()
|
||||
else:
|
||||
sprite.set_pixel(xx, yy, current_color)
|
||||
sprite_changed_this_frame = true
|
||||
"LightenDarken":
|
||||
|
@ -589,6 +624,7 @@ func draw_brush(sprite : Image, pos : Vector2, color : Color, current_mouse_butt
|
|||
vertical_mirror = Global.left_vertical_mirror
|
||||
ld = Global.left_ld
|
||||
ld_amount = Global.left_ld_amount
|
||||
|
||||
elif current_mouse_button == "right_mouse":
|
||||
brush_size = Global.right_brush_size
|
||||
brush_type = Global.current_right_brush_type
|
||||
|
@ -840,6 +876,44 @@ func flood_fill(sprite : Image, pos : Vector2, target_color : Color, replace_col
|
|||
q.append(south)
|
||||
sprite_changed_this_frame = true
|
||||
|
||||
|
||||
func pattern_fill(sprite : Image, pos : Vector2, pattern : Image, target_color : Color) -> void:
|
||||
pos = pos.floor()
|
||||
if !point_in_rectangle(pos, Vector2(west_limit - 1, north_limit - 1), Vector2(east_limit, south_limit)):
|
||||
return
|
||||
|
||||
pattern.lock()
|
||||
var pattern_size := pattern.get_size()
|
||||
var q = [pos]
|
||||
|
||||
for n in q:
|
||||
var west : Vector2 = n
|
||||
var east : Vector2 = n
|
||||
while west.x >= west_limit && sprite.get_pixelv(west) == target_color:
|
||||
west += Vector2.LEFT
|
||||
while east.x < east_limit && sprite.get_pixelv(east) == target_color:
|
||||
east += Vector2.RIGHT
|
||||
|
||||
for px in range(west.x + 1, east.x):
|
||||
var p := Vector2(px, n.y)
|
||||
var xx : int = int(px) % int(pattern_size.x)
|
||||
var yy : int = int(n.y) % int(pattern_size.y)
|
||||
var pattern_color : Color = pattern.get_pixel(xx, yy)
|
||||
if pattern_color == target_color:
|
||||
continue
|
||||
sprite.set_pixelv(p, pattern_color)
|
||||
|
||||
var north := p + Vector2.UP
|
||||
var south := p + Vector2.DOWN
|
||||
if north.y >= north_limit && sprite.get_pixelv(north) == target_color:
|
||||
q.append(north)
|
||||
if south.y < south_limit && sprite.get_pixelv(south) == target_color:
|
||||
q.append(south)
|
||||
|
||||
pattern.unlock()
|
||||
|
||||
|
||||
|
||||
# Algorithm based on http://members.chello.at/easyfilter/bresenham.html
|
||||
func plot_circle(sprite : Image, xm : int, ym : int, r : int, color : Color, fill := false) -> void:
|
||||
var radius := r # Used later for filling
|
||||
|
|
|
@ -150,7 +150,7 @@ func _ready() -> void:
|
|||
t[0].connect("pressed", self, "_on_Tool_pressed", [t[0]])
|
||||
|
||||
# Checks to see if it's 3.1.x
|
||||
if Engine.get_version_info().major == 3 && Engine.get_version_info().minor < 2:
|
||||
if Engine.get_version_info().major == 3 and Engine.get_version_info().minor < 2:
|
||||
Global.left_color_picker.get_picker().move_child(Global.left_color_picker.get_picker().get_child(0), 1)
|
||||
Global.right_color_picker.get_picker().move_child(Global.right_color_picker.get_picker().get_child(0), 1)
|
||||
|
||||
|
@ -190,7 +190,7 @@ func _input(event : InputEvent) -> void:
|
|||
Global.right_cursor.position = get_global_mouse_position() + Vector2(32, 32)
|
||||
Global.right_cursor.texture = Global.right_cursor_tool_texture
|
||||
|
||||
if event is InputEventKey && (event.scancode == KEY_ENTER || event.scancode == KEY_KP_ENTER):
|
||||
if event is InputEventKey and (event.scancode == KEY_ENTER or event.scancode == KEY_KP_ENTER):
|
||||
if get_focus_owner() is LineEdit:
|
||||
get_focus_owner().release_focus()
|
||||
|
||||
|
@ -308,7 +308,7 @@ func image_menu_id_pressed(id : int) -> void:
|
|||
var used_rect : Rect2 = Global.canvas.layers[0][0].get_used_rect()
|
||||
# However, if first layer is empty, loop through all layers until we find one that isn't
|
||||
var i := 0
|
||||
while(i < Global.canvas.layers.size() - 1 && Global.canvas.layers[i][0].get_used_rect() == Rect2(0, 0, 0, 0)):
|
||||
while(i < Global.canvas.layers.size() - 1 and Global.canvas.layers[i][0].get_used_rect() == Rect2(0, 0, 0, 0)):
|
||||
i += 1
|
||||
used_rect = Global.canvas.layers[i][0].get_used_rect()
|
||||
|
||||
|
@ -616,7 +616,7 @@ func _can_draw_false() -> void:
|
|||
|
||||
func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_left := true) -> void:
|
||||
var current_action := tool_pressed.name
|
||||
if (mouse_press && Input.is_action_just_released("left_mouse")) || (!mouse_press && key_for_left):
|
||||
if (mouse_press and Input.is_action_just_released("left_mouse")) or (!mouse_press and key_for_left):
|
||||
Global.current_left_tool = current_action
|
||||
|
||||
# Start from 3, so the label and checkboxes won't get invisible
|
||||
|
@ -628,7 +628,7 @@ func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_le
|
|||
Global.left_brush_type_container.visible = true
|
||||
# Global.left_brush_size_container.visible = true
|
||||
Global.left_mirror_container.visible = true
|
||||
if Global.current_left_brush_type == Global.Brush_Types.FILE || Global.current_left_brush_type == Global.Brush_Types.CUSTOM || Global.current_left_brush_type == Global.Brush_Types.RANDOM_FILE:
|
||||
if Global.current_left_brush_type == Global.Brush_Types.FILE or Global.current_left_brush_type == Global.Brush_Types.CUSTOM or Global.current_left_brush_type == Global.Brush_Types.RANDOM_FILE:
|
||||
Global.left_color_interpolation_container.visible = true
|
||||
elif current_action == "Eraser":
|
||||
Global.left_brush_type_container.visible = true
|
||||
|
@ -637,6 +637,8 @@ func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_le
|
|||
elif current_action == "Bucket":
|
||||
Global.left_fill_area_container.visible = true
|
||||
Global.left_mirror_container.visible = true
|
||||
if Global.current_left_brush_type == Global.Brush_Types.FILE or Global.current_left_brush_type == Global.Brush_Types.CUSTOM or Global.current_left_brush_type == Global.Brush_Types.RANDOM_FILE:
|
||||
Global.left_color_interpolation_container.visible = true
|
||||
elif current_action == "LightenDarken":
|
||||
# Global.left_brush_size_container.visible = true
|
||||
Global.left_ld_container.visible = true
|
||||
|
@ -644,7 +646,7 @@ func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_le
|
|||
elif current_action == "ColorPicker":
|
||||
Global.left_colorpicker_container.visible = true
|
||||
|
||||
elif (mouse_press && Input.is_action_just_released("right_mouse")) || (!mouse_press && !key_for_left):
|
||||
elif (mouse_press and Input.is_action_just_released("right_mouse")) or (!mouse_press and !key_for_left):
|
||||
Global.current_right_tool = current_action
|
||||
# Start from 3, so the label and checkboxes won't get invisible
|
||||
for i in range(3, Global.right_tool_options_container.get_child_count()):
|
||||
|
@ -655,7 +657,7 @@ func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_le
|
|||
Global.right_brush_type_container.visible = true
|
||||
# Global.right_brush_size_container.visible = true
|
||||
Global.right_mirror_container.visible = true
|
||||
if Global.current_right_brush_type == Global.Brush_Types.FILE || Global.current_right_brush_type == Global.Brush_Types.CUSTOM || Global.current_right_brush_type == Global.Brush_Types.RANDOM_FILE:
|
||||
if Global.current_right_brush_type == Global.Brush_Types.FILE or Global.current_right_brush_type == Global.Brush_Types.CUSTOM or Global.current_right_brush_type == Global.Brush_Types.RANDOM_FILE:
|
||||
Global.right_color_interpolation_container.visible = true
|
||||
elif current_action == "Eraser":
|
||||
Global.right_brush_type_container.visible = true
|
||||
|
@ -664,6 +666,8 @@ func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_le
|
|||
elif current_action == "Bucket":
|
||||
Global.right_fill_area_container.visible = true
|
||||
Global.right_mirror_container.visible = true
|
||||
if Global.current_right_brush_type == Global.Brush_Types.FILE or Global.current_right_brush_type == Global.Brush_Types.CUSTOM or Global.current_right_brush_type == Global.Brush_Types.RANDOM_FILE:
|
||||
Global.right_color_interpolation_container.visible = true
|
||||
elif current_action == "LightenDarken":
|
||||
# Global.right_brush_size_container.visible = true
|
||||
Global.right_ld_container.visible = true
|
||||
|
@ -673,7 +677,7 @@ func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_le
|
|||
|
||||
for t in tools:
|
||||
var tool_name : String = t[0].name
|
||||
if tool_name == Global.current_left_tool && tool_name == Global.current_right_tool:
|
||||
if tool_name == Global.current_left_tool and tool_name == Global.current_right_tool:
|
||||
t[0].texture_normal = load("res://Assets/Graphics/%s Themes/Tools/%s_l_r.png" % [Global.theme_type, tool_name])
|
||||
elif tool_name == Global.current_left_tool:
|
||||
t[0].texture_normal = load("res://Assets/Graphics/%s Themes/Tools/%s_l.png" % [Global.theme_type, tool_name])
|
||||
|
@ -726,7 +730,7 @@ func _on_ColorDefaults_pressed() -> void:
|
|||
func _on_LeftColorPickerButton_color_changed(color : Color) -> void:
|
||||
# If the color changed while it's on full transparency, make it opaque (GH issue #54)
|
||||
if color.a == 0:
|
||||
if previous_left_color.r != color.r || previous_left_color.g != color.g || previous_left_color.b != color.b:
|
||||
if previous_left_color.r != color.r or previous_left_color.g != color.g or previous_left_color.b != color.b:
|
||||
Global.left_color_picker.color.a = 1
|
||||
update_left_custom_brush()
|
||||
previous_left_color = color
|
||||
|
@ -735,7 +739,7 @@ func _on_LeftColorPickerButton_color_changed(color : Color) -> void:
|
|||
func _on_RightColorPickerButton_color_changed(color : Color) -> void:
|
||||
# If the color changed while it's on full transparency, make it opaque (GH issue #54)
|
||||
if color.a == 0:
|
||||
if previous_right_color.r != color.r || previous_right_color.g != color.g || previous_right_color.b != color.b:
|
||||
if previous_right_color.r != color.r or previous_right_color.g != color.g or previous_right_color.b != color.b:
|
||||
Global.right_color_picker.color.a = 1
|
||||
update_right_custom_brush()
|
||||
previous_right_color = color
|
||||
|
|
Loading…
Reference in a new issue