From c06999a57ff417d6108947c3c24e4b538584ba6c Mon Sep 17 00:00:00 2001 From: OverloadedOrama <35376950+OverloadedOrama@users.noreply.github.com> Date: Mon, 1 Jun 2020 02:32:44 +0300 Subject: [PATCH] Refactored DrawingAlgos.draw_brush(), made draw_pixel() method This also fixes alpha blending and lighting/darkening issues when drawing pixels with mirroring. --- CHANGELOG.md | 1 + src/Autoload/DrawingAlgos.gd | 208 ++++++++++++----------------------- src/Canvas.gd | 2 +- 3 files changed, 73 insertions(+), 138 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e730c5dde..5c10fcb28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Igor Santarek (jegor377), rob-a-bolton ### Fixed - Fixed failed imports of gpl palettes by adding support for the newer variant of gpl files. ([#250](https://github.com/Orama-Interactive/Pixelorama/pull/250)) +- Fixed alpha blending and lighting/darkening issues when drawing pixels with mirroring.

## [v0.7] - 2020-05-16 diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index 4ede97015..eea6f41d1 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -14,6 +14,31 @@ var mouse_press_pixels := [] # Cleared after mouse release var mouse_press_pressure_values := [] # Cleared after mouse release +func draw_pixel(sprite : Image, pos : Vector2, color : Color, current_mouse_button : int, current_action : int, drawer : Drawer, pen_pressure : float) -> void: + var pos_floored := pos.floor() + var current_pixel_color = sprite.get_pixelv(pos) + if current_action == Global.Tools.PENCIL && color.a < 1: + color = blend_colors(color, current_pixel_color) + + var saved_pixel_index = mouse_press_pixels.find(pos_floored) + # Don't draw the same pixel over and over and don't re-lighten/darken it + if current_pixel_color != color && (saved_pixel_index == -1 || pen_pressure > mouse_press_pressure_values[saved_pixel_index]): # Don't draw the same pixel over and over + if current_action == Global.Tools.LIGHTENDARKEN: + var ld : int = Global.ld_modes[current_mouse_button] + var ld_amount : float = Global.ld_amounts[current_mouse_button] + if ld == Global.Lighten_Darken_Mode.LIGHTEN: + color = current_pixel_color.lightened(ld_amount) + else: + color = current_pixel_color.darkened(ld_amount) + + if saved_pixel_index == -1: + mouse_press_pixels.append(pos_floored) + mouse_press_pressure_values.append(pen_pressure) + else: + mouse_press_pressure_values[saved_pixel_index] = pen_pressure + drawer.set_pixel(sprite, pos, color) + + func draw_brush(sprite : Image, pos : Vector2, color : Color, current_mouse_button : int, pen_pressure : float, current_action := -1) -> void: if Global.can_draw && Global.has_focus: var west_limit = Global.canvas.west_limit @@ -21,167 +46,76 @@ func draw_brush(sprite : Image, pos : Vector2, color : Color, current_mouse_butt var north_limit = Global.canvas.north_limit var south_limit = Global.canvas.south_limit - var brush_size := 1 - var brush_type = Global.Brush_Types.PIXEL - var brush_index := -1 - var custom_brush_image : Image - - var horizontal_mirror := false - var vertical_mirror := false - var pixel_perfect := false - - var ld := 0 - var ld_amount := 0.1 if Global.pressure_sensitivity_mode == Global.Pressure_Sensitivity.ALPHA: if current_action == Global.Tools.PENCIL: color.a *= pen_pressure elif current_action == Global.Tools.ERASER: # This is not working color.a *= (1.0 - pen_pressure) - if current_mouse_button == Global.Mouse_Button.LEFT: - brush_size = Global.brush_sizes[0] - brush_type = Global.current_brush_types[0] - brush_index = Global.custom_brush_indexes[0] - if brush_type != Global.Brush_Types.RANDOM_FILE: - custom_brush_image = Global.custom_brush_images[0] - else: # Handle random brush - var brush_button = Global.file_brush_container.get_child(brush_index + 3) - var random_index = randi() % brush_button.random_brushes.size() - custom_brush_image = Image.new() - custom_brush_image.copy_from(brush_button.random_brushes[random_index]) - var custom_brush_size = custom_brush_image.get_size() - custom_brush_image.resize(custom_brush_size.x * brush_size, custom_brush_size.y * brush_size, Image.INTERPOLATE_NEAREST) - custom_brush_image = Global.blend_image_with_color(custom_brush_image, color, Global.interpolate_spinboxes[0].value / 100) - custom_brush_image.lock() - horizontal_mirror = Global.horizontal_mirror[0] - vertical_mirror = Global.vertical_mirror[0] - pixel_perfect = Global.pixel_perfect[0] - ld = Global.ld_modes[0] - ld_amount = Global.ld_amounts[0] + var brush_size : int = Global.brush_sizes[current_mouse_button] + var brush_type : int = Global.current_brush_types[current_mouse_button] + var brush_index : int = Global.custom_brush_indexes[current_mouse_button] - elif current_mouse_button == Global.Mouse_Button.RIGHT: - brush_size = Global.brush_sizes[1] - brush_type = Global.current_brush_types[1] - brush_index = Global.custom_brush_indexes[1] - if brush_type != Global.Brush_Types.RANDOM_FILE: - custom_brush_image = Global.custom_brush_images[1] - else: # Handle random brush - var brush_button = Global.file_brush_container.get_child(brush_index + 3) - var random_index = randi() % brush_button.random_brushes.size() - custom_brush_image = Image.new() - custom_brush_image.copy_from(brush_button.random_brushes[random_index]) - var custom_brush_size = custom_brush_image.get_size() - custom_brush_image.resize(custom_brush_size.x * brush_size, custom_brush_size.y * brush_size, Image.INTERPOLATE_NEAREST) - custom_brush_image = Global.blend_image_with_color(custom_brush_image, color, Global.interpolate_spinboxes[1].value / 100) - custom_brush_image.lock() - - horizontal_mirror = Global.horizontal_mirror[1] - vertical_mirror = Global.vertical_mirror[1] - pixel_perfect = Global.pixel_perfect[1] - ld = Global.ld_modes[1] - ld_amount = Global.ld_amounts[1] - - var start_pos_x - var start_pos_y - var end_pos_x - var end_pos_y + var horizontal_mirror : bool = Global.horizontal_mirror[current_mouse_button] + var vertical_mirror : bool = Global.vertical_mirror[current_mouse_button] + var pixel_perfect : bool = Global.pixel_perfect[current_mouse_button] if brush_type == Global.Brush_Types.PIXEL || current_action == Global.Tools.LIGHTENDARKEN: - var drawer = pixel_perfect_drawer if pixel_perfect else simple_drawer - var drawer_v_mirror = pixel_perfect_drawer_v_mirror if pixel_perfect else simple_drawer - var drawer_h_mirror = pixel_perfect_drawer_h_mirror if pixel_perfect else simple_drawer - var drawer_hv_mirror = pixel_perfect_drawer_hv_mirror if pixel_perfect else simple_drawer + var start_pos_x = pos.x - (brush_size >> 1) + var start_pos_y = pos.y - (brush_size >> 1) + var end_pos_x = start_pos_x + brush_size + var end_pos_y = start_pos_y + brush_size - start_pos_x = pos.x - (brush_size >> 1) - start_pos_y = pos.y - (brush_size >> 1) - end_pos_x = start_pos_x + brush_size - end_pos_y = start_pos_y + brush_size for cur_pos_x in range(start_pos_x, end_pos_x): for cur_pos_y in range(start_pos_y, end_pos_y): if point_in_rectangle(Vector2(cur_pos_x, cur_pos_y), Vector2(west_limit - 1, north_limit - 1), Vector2(east_limit, south_limit)): - var pos_floored := Vector2(cur_pos_x, cur_pos_y).floor() - # Don't draw the same pixel over and over and don't re-lighten/darken it - var current_pixel_color : Color = sprite.get_pixel(cur_pos_x, cur_pos_y) - var _c := color - if current_action == Global.Tools.PENCIL && color.a < 1: - _c = DrawingAlgos.blend_colors(color, current_pixel_color) + var drawer = pixel_perfect_drawer if pixel_perfect else simple_drawer + draw_pixel(sprite, Vector2(cur_pos_x, cur_pos_y), color, current_mouse_button, current_action, drawer, pen_pressure) - var saved_pixel_index = DrawingAlgos.mouse_press_pixels.find(pos_floored) - if current_pixel_color != _c && (saved_pixel_index == -1 || pen_pressure > DrawingAlgos.mouse_press_pressure_values[saved_pixel_index]): - if current_action == Global.Tools.LIGHTENDARKEN: - _c = current_pixel_color - if _c.a > 0: - if ld == 0: # Lighten - _c = current_pixel_color.lightened(ld_amount) - else: # Darken - _c = current_pixel_color.darkened(ld_amount) + # Handle mirroring + var mirror_x = east_limit + west_limit - cur_pos_x - 1 + var mirror_y = south_limit + north_limit - cur_pos_y - 1 + if horizontal_mirror: + var drawer_h_mirror = pixel_perfect_drawer_h_mirror if pixel_perfect else simple_drawer + draw_pixel(sprite, Vector2(mirror_x, cur_pos_y), color, current_mouse_button, current_action, drawer_h_mirror, pen_pressure) + if vertical_mirror: + var drawer_v_mirror = pixel_perfect_drawer_v_mirror if pixel_perfect else simple_drawer + draw_pixel(sprite, Vector2(cur_pos_x, mirror_y), color, current_mouse_button, current_action, drawer_v_mirror, pen_pressure) + if horizontal_mirror && vertical_mirror: + var drawer_hv_mirror = pixel_perfect_drawer_hv_mirror if pixel_perfect else simple_drawer + draw_pixel(sprite, Vector2(mirror_x, mirror_y), color, current_mouse_button, current_action, drawer_hv_mirror, pen_pressure) - if saved_pixel_index == -1: - DrawingAlgos.mouse_press_pixels.append(pos_floored) - DrawingAlgos.mouse_press_pressure_values.append(pen_pressure) - else: - DrawingAlgos.mouse_press_pressure_values[saved_pixel_index] = pen_pressure - drawer.set_pixel(sprite, Vector2(cur_pos_x, cur_pos_y), _c) - - # Handle mirroring - var mirror_x = east_limit + west_limit - cur_pos_x - 1 - var mirror_y = south_limit + north_limit - cur_pos_y - 1 - if horizontal_mirror: - current_pixel_color = sprite.get_pixel(mirror_x, cur_pos_y) - if current_pixel_color != _c: # don't draw the same pixel over and over - if current_action == Global.Tools.LIGHTENDARKEN: - if ld == 0: # Lighten - _c = current_pixel_color.lightened(ld_amount) - else: - _c = current_pixel_color.darkened(ld_amount) - - DrawingAlgos.mouse_press_pixels.append(pos_floored) - DrawingAlgos.mouse_press_pressure_values.append(pen_pressure) - drawer_h_mirror.set_pixel(sprite, Vector2(mirror_x, cur_pos_y), _c) - - if vertical_mirror: - current_pixel_color = sprite.get_pixel(cur_pos_x, mirror_y) - if current_pixel_color != _c: # don't draw the same pixel over and over - if current_action == Global.Tools.LIGHTENDARKEN: - if ld == 0: # Lighten - _c = current_pixel_color.lightened(ld_amount) - else: - _c = current_pixel_color.darkened(ld_amount) - DrawingAlgos.mouse_press_pixels.append(pos_floored) - DrawingAlgos.mouse_press_pressure_values.append(pen_pressure) - drawer_v_mirror.set_pixel(sprite, Vector2(cur_pos_x, mirror_y), _c) - - if horizontal_mirror && vertical_mirror: - current_pixel_color = sprite.get_pixel(mirror_x, mirror_y) - if current_pixel_color != _c: # don't draw the same pixel over and over - if current_action == Global.Tools.LIGHTENDARKEN: - if ld == 0: # Lighten - _c = current_pixel_color.lightened(ld_amount) - else: - _c = current_pixel_color.darkened(ld_amount) - - DrawingAlgos.mouse_press_pixels.append(pos_floored) - DrawingAlgos.mouse_press_pressure_values.append(pen_pressure) - drawer_hv_mirror.set_pixel(sprite, Vector2(mirror_x, mirror_y), _c) - - Global.canvas.sprite_changed_this_frame = true + Global.canvas.sprite_changed_this_frame = true elif brush_type == Global.Brush_Types.CIRCLE || brush_type == Global.Brush_Types.FILLED_CIRCLE: - DrawingAlgos.plot_circle(sprite, pos.x, pos.y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) + plot_circle(sprite, pos.x, pos.y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) # Handle mirroring var mirror_x = east_limit + west_limit - pos.x var mirror_y = south_limit + north_limit - pos.y if horizontal_mirror: - DrawingAlgos.plot_circle(sprite, mirror_x, pos.y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) + plot_circle(sprite, mirror_x, pos.y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) if vertical_mirror: - DrawingAlgos.plot_circle(sprite, pos.x, mirror_y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) + plot_circle(sprite, pos.x, mirror_y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) if horizontal_mirror && vertical_mirror: - DrawingAlgos.plot_circle(sprite, mirror_x, mirror_y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) + plot_circle(sprite, mirror_x, mirror_y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) Global.canvas.sprite_changed_this_frame = true else: + var custom_brush_image : Image + if brush_type != Global.Brush_Types.RANDOM_FILE: + custom_brush_image = Global.custom_brush_images[current_mouse_button] + else: # Handle random brush + var brush_button = Global.file_brush_container.get_child(brush_index + 3) + var random_index = randi() % brush_button.random_brushes.size() + custom_brush_image = Image.new() + custom_brush_image.copy_from(brush_button.random_brushes[random_index]) + var custom_brush_size = custom_brush_image.get_size() + custom_brush_image.resize(custom_brush_size.x * brush_size, custom_brush_size.y * brush_size, Image.INTERPOLATE_NEAREST) + custom_brush_image = Global.blend_image_with_color(custom_brush_image, color, Global.interpolate_spinboxes[current_mouse_button].value / 100) + custom_brush_image.lock() + var custom_brush_size := custom_brush_image.get_size() - Vector2.ONE pos = pos.floor() var dst := rectangle_center(pos, custom_brush_size) @@ -220,13 +154,13 @@ func draw_brush(sprite : Image, pos : Vector2, color : Color, current_mouse_butt mirror_y -= 1 # Use custom blend function cause of godot's issue #31124 if color.a > 0: # If it's the pencil - DrawingAlgos.blend_rect(sprite, custom_brush_image, src_rect, dst) + blend_rect(sprite, custom_brush_image, src_rect, dst) if horizontal_mirror: - DrawingAlgos.blend_rect(sprite, custom_brush_image, src_rect, Vector2(mirror_x, dst.y)) + blend_rect(sprite, custom_brush_image, src_rect, Vector2(mirror_x, dst.y)) if vertical_mirror: - DrawingAlgos.blend_rect(sprite, custom_brush_image, src_rect, Vector2(dst.x, mirror_y)) + blend_rect(sprite, custom_brush_image, src_rect, Vector2(dst.x, mirror_y)) if horizontal_mirror && vertical_mirror: - DrawingAlgos.blend_rect(sprite, custom_brush_image, src_rect, Vector2(mirror_x, mirror_y)) + blend_rect(sprite, custom_brush_image, src_rect, Vector2(mirror_x, mirror_y)) else: # if it's transparent - if it's the eraser var custom_brush := Image.new() diff --git a/src/Canvas.gd b/src/Canvas.gd index 682cf7fad..a3bed5640 100644 --- a/src/Canvas.gd +++ b/src/Canvas.gd @@ -118,7 +118,7 @@ func _draw() -> void: else: if Global.current_tools[i] == Global.Tools.PENCIL || Global.current_tools[i] == Global.Tools.ERASER: var custom_brush_size = Global.custom_brush_images[i].get_size() - Vector2.ONE - var dst := DrawingAlgos.rectangle_center(mouse_pos, custom_brush_size) + var dst : Vector2 = DrawingAlgos.rectangle_center(mouse_pos, custom_brush_size) draw_texture(Global.custom_brush_textures[i], dst)