From dc9ba6dd9ccd0d868b63bc10a5bc1c334a62c536 Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas Date: Sat, 9 Mar 2024 02:47:13 +0200 Subject: [PATCH] Implement alpha lock as a global tool option --- assets/graphics/misc/alpha_lock_off.png | Bin 0 -> 138 bytes .../graphics/misc/alpha_lock_off.png.import | 34 +++++++++++++++++ assets/graphics/misc/alpha_lock_on.png | Bin 0 -> 229 bytes assets/graphics/misc/alpha_lock_on.png.import | 34 +++++++++++++++++ src/Autoload/Tools.gd | 7 ++++ src/Classes/Drawers.gd | 13 ++++--- src/Tools/DesignTools/Bucket.gd | 8 +++- src/Tools/DesignTools/Pencil.gd | 14 +++++-- src/UI/GlobalToolOptions/GlobalToolOptions.gd | 11 ++++++ .../GlobalToolOptions/GlobalToolOptions.tscn | 35 +++++++++++++++--- 10 files changed, 139 insertions(+), 17 deletions(-) create mode 100644 assets/graphics/misc/alpha_lock_off.png create mode 100644 assets/graphics/misc/alpha_lock_off.png.import create mode 100644 assets/graphics/misc/alpha_lock_on.png create mode 100644 assets/graphics/misc/alpha_lock_on.png.import diff --git a/assets/graphics/misc/alpha_lock_off.png b/assets/graphics/misc/alpha_lock_off.png new file mode 100644 index 0000000000000000000000000000000000000000..9c6dda6111dd99ffdde4b8995f2b389d75ce8a1a GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw{1|(OCFP#RY7>k44ofy`glX(f`xOloahFJ6_ zuUWtT|M>>yB}mdKI;Vst0L|?!w*UYD literal 0 HcmV?d00001 diff --git a/assets/graphics/misc/alpha_lock_off.png.import b/assets/graphics/misc/alpha_lock_off.png.import new file mode 100644 index 00000000000..2eac6603e5e --- /dev/null +++ b/assets/graphics/misc/alpha_lock_off.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://j8eywwy082a4" +path="res://.godot/imported/alpha_lock_off.png-2b88d446a40bc5d304eb489a1531dbc7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/graphics/misc/alpha_lock_off.png" +dest_files=["res://.godot/imported/alpha_lock_off.png-2b88d446a40bc5d304eb489a1531dbc7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/graphics/misc/alpha_lock_on.png b/assets/graphics/misc/alpha_lock_on.png new file mode 100644 index 0000000000000000000000000000000000000000..ea269ec112e5f2ddc00aae2868719501ea79479a GIT binary patch literal 229 zcmV^P)Px#pGibPR5*>*RKX3zFbGRe-NO524U09{k2&sMmF_4Iq^dgAuOtvFIEIbndnA~1 zW}%^~Y3!9oF5o$&`zisz&)&?gkpei8L}woNlwa9KL_+JRYH7F4%tD`fEj=m;!tz&y ztDKgmBnQb(YLE1rtV{f#juMe@U16`L&4I%{o;14~zSL_6;Pl&-zG?Z@rB$1jz26xg f5uP(oZz25vRTVcxhE`C)00000NkvXXu0mjf=aODs literal 0 HcmV?d00001 diff --git a/assets/graphics/misc/alpha_lock_on.png.import b/assets/graphics/misc/alpha_lock_on.png.import new file mode 100644 index 00000000000..0dfc7441ecd --- /dev/null +++ b/assets/graphics/misc/alpha_lock_on.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cecc5pdyv1qqc" +path="res://.godot/imported/alpha_lock_on.png-b504142d180d946e470db4c9a8a68837.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/graphics/misc/alpha_lock_on.png" +dest_files=["res://.godot/imported/alpha_lock_on.png-b504142d180d946e470db4c9a8a68837.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/src/Autoload/Tools.gd b/src/Autoload/Tools.gd index a9eb19bae71..2bb94936b51 100644 --- a/src/Autoload/Tools.gd +++ b/src/Autoload/Tools.gd @@ -8,6 +8,7 @@ var picking_color_for := MOUSE_BUTTON_LEFT var horizontal_mirror := false var vertical_mirror := false var pixel_perfect := false +var alpha_locked := false # Dynamics var stabilizer_enabled := false @@ -568,6 +569,12 @@ func handle_draw(position: Vector2i, event: InputEvent) -> void: Global.cursor_position_label.text = text +## Returns [code]true[/code] if [member alpha_locked] is [code]true[/code] +## and the [param image]'s pixel at [param position] is transparent. +func check_alpha_lock(image: Image, position: Vector2i) -> bool: + return alpha_locked and is_zero_approx(image.get_pixelv(position).a) + + func get_alpha_dynamic(strength := 1.0) -> float: if dynamics_alpha == Dynamics.PRESSURE: strength *= lerpf(alpha_min, alpha_max, pen_pressure) diff --git a/src/Classes/Drawers.gd b/src/Classes/Drawers.gd index 1698778c78b..3530ae0f3da 100644 --- a/src/Classes/Drawers.gd +++ b/src/Classes/Drawers.gd @@ -67,12 +67,13 @@ func reset() -> void: func set_pixel(image: Image, position: Vector2i, color: Color, ignore_mirroring := false) -> void: var project := Global.current_project - drawers[0].set_pixel(image, position, color, color_op) + if not Tools.check_alpha_lock(image, position): + drawers[0].set_pixel(image, position, color, color_op) if ignore_mirroring: return # Handle mirroring - var i := 1 - for mirror_pos in Tools.get_mirrored_positions(position, project): - if project.can_pixel_get_drawn(mirror_pos): - drawers[i].set_pixel(image, mirror_pos, color, color_op) - i += 1 + var mirrored_positions := Tools.get_mirrored_positions(position, project) + for i in mirrored_positions.size(): + var mirror_pos := mirrored_positions[i] + if project.can_pixel_get_drawn(mirror_pos) && not Tools.check_alpha_lock(image, mirror_pos): + drawers[i + 1].set_pixel(image, mirror_pos, color, color_op) diff --git a/src/Tools/DesignTools/Bucket.gd b/src/Tools/DesignTools/Bucket.gd index bcdae748d8f..7b9f3f228ce 100644 --- a/src/Tools/DesignTools/Bucket.gd +++ b/src/Tools/DesignTools/Bucket.gd @@ -182,6 +182,8 @@ func fill_in_color(pos: Vector2i) -> void: var project := Global.current_project var images := _get_selected_draw_images() for image in images: + if Tools.check_alpha_lock(image, pos): + continue var color: Color = image.get_pixelv(pos) var pattern_image: Image if _fill_with == FillWith.COLOR or _pattern == null: @@ -296,11 +298,11 @@ func _add_new_segment(y := 0) -> void: ## Fill an horizontal segment around the specified position, and adds it to the ## list of segments filled. Returns the first x coordinate after the part of the ## line that has been filled. +## Τhis method is called by [method _flood_fill] after the required data structures +## have been initialized. func _flood_line_around_point( pos: Vector2i, project: Project, image: Image, src_color: Color ) -> int: - # this method is called by `_flood_fill` after the required data structures - # have been initialized if not image.get_pixelv(pos).is_equal_approx(src_color): return pos.x + 1 var west := pos @@ -382,6 +384,8 @@ func _flood_fill(pos: Vector2i) -> void: var project := Global.current_project var images := _get_selected_draw_images() for image in images: + if Tools.check_alpha_lock(image, pos): + continue var color: Color = image.get_pixelv(pos) if _fill_with == FillWith.COLOR or _pattern == null: # end early if we are filling with the same color diff --git a/src/Tools/DesignTools/Pencil.gd b/src/Tools/DesignTools/Pencil.gd index c429b70ec5f..1ee1dfcc941 100644 --- a/src/Tools/DesignTools/Pencil.gd +++ b/src/Tools/DesignTools/Pencil.gd @@ -196,12 +196,20 @@ func draw_end(pos: Vector2i) -> void: _spacing_mode = _old_spacing_mode -func _draw_brush_image(image: Image, src_rect: Rect2i, dst: Vector2i) -> void: +func _draw_brush_image(brush_image: Image, src_rect: Rect2i, dst: Vector2i) -> void: _changed = true var images := _get_selected_draw_images() if _overwrite: for draw_image in images: - draw_image.blit_rect(image, src_rect, dst) + if Tools.alpha_locked: + var mask := draw_image.get_region(Rect2i(dst, brush_image.get_size())) + draw_image.blit_rect_mask(brush_image, mask, src_rect, dst) + else: + draw_image.blit_rect(brush_image, src_rect, dst) else: for draw_image in images: - draw_image.blend_rect(image, src_rect, dst) + if Tools.alpha_locked: + var mask := draw_image.get_region(Rect2i(dst, brush_image.get_size())) + draw_image.blend_rect_mask(brush_image, mask, src_rect, dst) + else: + draw_image.blend_rect(brush_image, src_rect, dst) diff --git a/src/UI/GlobalToolOptions/GlobalToolOptions.gd b/src/UI/GlobalToolOptions/GlobalToolOptions.gd index 6bffb9b4e4c..f93341470bc 100644 --- a/src/UI/GlobalToolOptions/GlobalToolOptions.gd +++ b/src/UI/GlobalToolOptions/GlobalToolOptions.gd @@ -8,6 +8,7 @@ enum { ALPHA, SIZE } @onready var horizontal_mirror: BaseButton = grid_container.get_node("Horizontal") @onready var vertical_mirror: BaseButton = grid_container.get_node("Vertical") @onready var pixel_perfect: BaseButton = grid_container.get_node("PixelPerfect") +@onready var alpha_lock: BaseButton = grid_container.get_node("AlphaLock") @onready var dynamics: Button = $"%Dynamics" @onready var dynamics_panel: PopupPanel = $DynamicsPanel @@ -100,6 +101,16 @@ func _on_PixelPerfect_toggled(button_pressed: bool) -> void: Global.change_button_texturerect(texture_button, file_name) +func _on_alpha_lock_toggled(toggled_on: bool) -> void: + Tools.alpha_locked = toggled_on + Global.config_cache.set_value("preferences", "alpha_locked", toggled_on) + var texture_button: TextureRect = alpha_lock.get_node("TextureRect") + var file_name := "alpha_lock_on.png" + if not toggled_on: + file_name = "alpha_lock_off.png" + Global.change_button_texturerect(texture_button, file_name) + + func _on_Dynamics_pressed() -> void: var pos := dynamics.global_position + Vector2(0, 32) dynamics_panel.popup(Rect2(pos, dynamics_panel.size)) diff --git a/src/UI/GlobalToolOptions/GlobalToolOptions.tscn b/src/UI/GlobalToolOptions/GlobalToolOptions.tscn index 818a210ac84..523cf91fb31 100644 --- a/src/UI/GlobalToolOptions/GlobalToolOptions.tscn +++ b/src/UI/GlobalToolOptions/GlobalToolOptions.tscn @@ -1,10 +1,11 @@ -[gd_scene load_steps=20 format=3 uid="uid://wo0hqxkst808"] +[gd_scene load_steps=21 format=3 uid="uid://wo0hqxkst808"] [ext_resource type="Texture2D" uid="uid://cjrokejjsp5dm" path="res://assets/graphics/misc/horizontal_mirror_off.png" id="1"] [ext_resource type="Texture2D" uid="uid://hiduvaa73fr6" path="res://assets/graphics/misc/vertical_mirror_off.png" id="2"] [ext_resource type="Script" path="res://src/UI/GlobalToolOptions/GlobalToolOptions.gd" id="3"] [ext_resource type="Texture2D" uid="uid://22h12g8p3jtd" path="res://assets/graphics/misc/pixel_perfect_off.png" id="4"] [ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="5"] +[ext_resource type="Texture2D" uid="uid://j8eywwy082a4" path="res://assets/graphics/misc/alpha_lock_off.png" id="5_jv20x"] [ext_resource type="Texture2D" uid="uid://dg3dumyfj1682" path="res://assets/graphics/misc/dynamics.png" id="6"] [ext_resource type="Texture2D" uid="uid://di8au2u87jgv5" path="res://assets/graphics/misc/uncheck.png" id="7"] [ext_resource type="PackedScene" uid="uid://bmsc0s03pwji4" path="res://src/UI/Nodes/MaxMinEdit.tscn" id="8"] @@ -62,7 +63,7 @@ size_flags_vertical = 3 [node name="GridContainer" type="GridContainer" parent="ScrollContainer/CenterContainer"] layout_mode = 2 size_flags_vertical = 0 -columns = 4 +columns = 5 [node name="Horizontal" type="Button" parent="ScrollContainer/CenterContainer/GridContainer" groups=["UIButtons"]] custom_minimum_size = Vector2(32, 32) @@ -125,6 +126,27 @@ offset_right = 11.0 offset_bottom = 10.0 texture = ExtResource("4") +[node name="AlphaLock" type="Button" parent="ScrollContainer/CenterContainer/GridContainer"] +custom_minimum_size = Vector2(32, 32) +layout_mode = 2 +tooltip_text = "Pixel Perfect +Makes lines smooth by removing the extra pixels on the edges" +mouse_default_cursor_shape = 2 +toggle_mode = true +shortcut = SubResource("Shortcut_vcyug") + +[node name="TextureRect" type="TextureRect" parent="ScrollContainer/CenterContainer/GridContainer/AlphaLock"] +layout_mode = 0 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -11.0 +offset_top = -10.0 +offset_right = 11.0 +offset_bottom = 10.0 +texture = ExtResource("5_jv20x") + [node name="Dynamics" type="Button" parent="ScrollContainer/CenterContainer/GridContainer" groups=["UIButtons"]] unique_name_in_owner = true custom_minimum_size = Vector2(32, 32) @@ -149,10 +171,10 @@ canvas_item_default_texture_filter = 0 size = Vector2i(300, 334) [node name="VBoxContainer" type="VBoxContainer" parent="DynamicsPanel"] -offset_left = 8.0 -offset_top = 8.0 -offset_right = 292.0 -offset_bottom = 326.0 +offset_left = 4.0 +offset_top = 4.0 +offset_right = 296.0 +offset_bottom = 330.0 [node name="StabilizerContainer" type="HBoxContainer" parent="DynamicsPanel/VBoxContainer"] layout_mode = 2 @@ -436,6 +458,7 @@ offset_bottom = 23.0 [connection signal="toggled" from="ScrollContainer/CenterContainer/GridContainer/Horizontal" to="." method="_on_Horizontal_toggled"] [connection signal="toggled" from="ScrollContainer/CenterContainer/GridContainer/Vertical" to="." method="_on_Vertical_toggled"] [connection signal="toggled" from="ScrollContainer/CenterContainer/GridContainer/PixelPerfect" to="." method="_on_PixelPerfect_toggled"] +[connection signal="toggled" from="ScrollContainer/CenterContainer/GridContainer/AlphaLock" to="." method="_on_alpha_lock_toggled"] [connection signal="pressed" from="ScrollContainer/CenterContainer/GridContainer/Dynamics" to="." method="_on_Dynamics_pressed"] [connection signal="toggled" from="DynamicsPanel/VBoxContainer/StabilizerContainer/EnableStabilizer" to="." method="_on_enable_stabilizer_toggled"] [connection signal="value_changed" from="DynamicsPanel/VBoxContainer/StabilizerContainer/StabilizerValue" to="." method="_on_stabilizer_value_value_changed"]