1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-07 10:59:49 +00:00

Make bucket fill "Whole Selection" option work with patterns

Also fix issue with similar area and color fill where if the selected color is the same as the pixel's color in mouse position, the operation stops even if there are other cels selected.
This commit is contained in:
Emmanouil Papadeas 2022-09-18 19:22:06 +03:00
parent cac9b67335
commit 63bc2332db
2 changed files with 69 additions and 16 deletions

View file

@ -0,0 +1,17 @@
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D selection;
uniform sampler2D pattern;
uniform vec2 size;
uniform vec2 pattern_size;
uniform vec2 pattern_uv_offset;
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV);
vec4 col = original_color;
col = textureLod(pattern, UV * (size / pattern_size) + pattern_uv_offset, 0.0);
COLOR = mix(original_color, col, selection_color.a);
}

View file

@ -4,6 +4,7 @@ enum FillArea { AREA, COLORS, SELECTION }
enum FillWith { COLOR, PATTERN } enum FillWith { COLOR, PATTERN }
const COLOR_REPLACE_SHADER := preload("res://src/Shaders/ColorReplace.shader") const COLOR_REPLACE_SHADER := preload("res://src/Shaders/ColorReplace.shader")
const PATTERN_FILL_SHADER := preload("res://src/Shaders/PatternFill.gdshader")
var _prev_mode := 0 var _prev_mode := 0
var _pattern: Patterns.Pattern var _pattern: Patterns.Pattern
@ -180,13 +181,13 @@ func draw_end(position: Vector2) -> void:
func fill_in_color(position: Vector2) -> void: func fill_in_color(position: Vector2) -> void:
var project: Project = Global.current_project var project: Project = Global.current_project
var color: Color = _get_draw_image().get_pixelv(position)
var images := _get_selected_draw_images() var images := _get_selected_draw_images()
for image in images: for image in images:
var color: Color = image.get_pixelv(position)
var pattern_image: Image var pattern_image: Image
if _fill_with == FillWith.COLOR or _pattern == null: if _fill_with == FillWith.COLOR or _pattern == null:
if tool_slot.color.is_equal_approx(color): if tool_slot.color.is_equal_approx(color):
return continue
else: else:
# End early if we are filling with an empty pattern # End early if we are filling with an empty pattern
pattern_image = _pattern.image pattern_image = _pattern.image
@ -250,25 +251,60 @@ func fill_in_area(position: Vector2) -> void:
func fill_in_selection() -> void: func fill_in_selection() -> void:
var project: Project = Global.current_project var project: Project = Global.current_project
var images := _get_selected_draw_images() var images := _get_selected_draw_images()
if project.has_selection: if _fill_with == FillWith.COLOR or _pattern == null:
var filler := Image.new() if project.has_selection:
filler.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) var filler := Image.new()
filler.fill(tool_slot.color) filler.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
var rect: Rect2 = Global.canvas.selection.big_bounding_rectangle filler.fill(tool_slot.color)
var selection_map_copy := SelectionMap.new() var rect: Rect2 = Global.canvas.selection.big_bounding_rectangle
selection_map_copy.copy_from(project.selection_map) var selection_map_copy := SelectionMap.new()
# In case the selection map is bigger than the canvas selection_map_copy.copy_from(project.selection_map)
selection_map_copy.crop(project.size.x, project.size.y) # In case the selection map is bigger than the canvas
for image in images: selection_map_copy.crop(project.size.x, project.size.y)
image.blit_rect_mask(filler, selection_map_copy, rect, rect.position) for image in images:
image.blit_rect_mask(filler, selection_map_copy, rect, rect.position)
else:
for image in images:
image.fill(tool_slot.color)
else: else:
# End early if we are filling with an empty pattern
var pattern_image: Image = _pattern.image
var pattern_size := pattern_image.get_size()
if pattern_size.x == 0 or pattern_size.y == 0:
return
var selection: Image
var selection_tex := ImageTexture.new()
if project.has_selection:
selection = project.selection_map
else:
selection = Image.new()
selection.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
selection.fill(Color(1, 1, 1, 1))
selection_tex.create_from_image(selection)
var pattern_tex := ImageTexture.new()
if _pattern and pattern_image:
pattern_tex.create_from_image(pattern_image)
var params := {
"selection": selection_tex,
"size": project.size,
"pattern": pattern_tex,
"pattern_size": pattern_tex.get_size(),
# pixel offset converted to pattern uv offset
"pattern_uv_offset":
Vector2.ONE / pattern_tex.get_size() * Vector2(_offset_x, _offset_y),
}
for image in images: for image in images:
image.fill(tool_slot.color) var gen := ShaderImageEffect.new()
gen.generate_image(image, PATTERN_FILL_SHADER, params, project.size)
# Add a new segment to the array # Add a new segment to the array
func _add_new_segment(y: int = 0) -> void: func _add_new_segment(y: int = 0) -> void:
var segment = {} var segment := {}
segment.flooding = false segment.flooding = false
segment.todo_above = false segment.todo_above = false
segment.todo_below = false segment.todo_below = false
@ -374,7 +410,7 @@ func _flood_fill(position: Vector2) -> void:
if _fill_with == FillWith.COLOR or _pattern == null: if _fill_with == FillWith.COLOR or _pattern == null:
# end early if we are filling with the same color # end early if we are filling with the same color
if tool_slot.color.is_equal_approx(color): if tool_slot.color.is_equal_approx(color):
return continue
else: else:
# end early if we are filling with an empty pattern # end early if we are filling with an empty pattern
var pattern_size := _pattern.image.get_size() var pattern_size := _pattern.image.get_size()