From 1678738d75f68f2ae29e2b30501e60314d20d9d6 Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Date: Sat, 10 Aug 2024 18:43:04 +0300 Subject: [PATCH] Add tolerance to the magic wand, rename "similarity" to "tolerance" in the select by color tool and make it work the inverse way Continuation of b0a284583b6b9d38d407221c53ab46574c4a614b for the selection tools. --- src/Shaders/ColorSelect.gdshader | 16 +++++++++--- src/Tools/SelectionTools/ColorSelect.gd | 14 +++++----- src/Tools/SelectionTools/ColorSelect.tscn | 18 +++++++++---- src/Tools/SelectionTools/MagicWand.gd | 32 ++++++++++++++++++++--- src/Tools/SelectionTools/MagicWand.tscn | 20 +++++++++++++- 5 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/Shaders/ColorSelect.gdshader b/src/Shaders/ColorSelect.gdshader index 0fcbae627..f568a2eaa 100644 --- a/src/Shaders/ColorSelect.gdshader +++ b/src/Shaders/ColorSelect.gdshader @@ -3,18 +3,26 @@ render_mode unshaded; uniform sampler2D selection : filter_nearest, hint_default_black; uniform vec4 color; -uniform float similarity_percent : hint_range(0.0, 100.0); +uniform float tolerance : hint_range(0.0, 1.0); uniform int operation = 0; // 0 = add, 1 = subtract, 2 = intersect +bool similar_colors(vec4 c1, vec4 c2, float tol) { + return ( + abs(c1.r - c2.r) <= tol + && abs(c1.g - c2.g) <= tol + && abs(c1.b - c2.b) <= tol + && abs(c1.a - c2.a) <= tol + ); +} + void fragment() { vec4 original_color = texture(TEXTURE, UV); - float diff = distance(original_color, color); - float similarity = abs(2.0 - ((similarity_percent/100.0) * 2.0)); + vec4 col = texture(selection, UV); if (col.rgb == vec3(0.0)) col.a = 0.0; - if (diff <= similarity) + if (similar_colors(original_color, color, tolerance)) { if (operation == 0) col = vec4(1.0); diff --git a/src/Tools/SelectionTools/ColorSelect.gd b/src/Tools/SelectionTools/ColorSelect.gd index a6fa33e5b..1e172929f 100644 --- a/src/Tools/SelectionTools/ColorSelect.gd +++ b/src/Tools/SelectionTools/ColorSelect.gd @@ -1,25 +1,25 @@ extends BaseSelectionTool var shader := preload("res://src/Shaders/ColorSelect.gdshader") -var _similarity := 100 +var _tolerance := 0.003 func get_config() -> Dictionary: var config := super.get_config() - config["similarity"] = _similarity + config["tolerance"] = _tolerance return config func set_config(config: Dictionary) -> void: - _similarity = config.get("similarity", _similarity) + _tolerance = config.get("tolerance", _tolerance) func update_config() -> void: - $SimilaritySlider.value = _similarity + $ToleranceSlider.value = _tolerance * 255.0 -func _on_Similarity_value_changed(value: float) -> void: - _similarity = value +func _on_tolerance_slider_value_changed(value: float) -> void: + _tolerance = value / 255.0 update_config() save_config() @@ -41,7 +41,7 @@ func apply_selection(pos: Vector2i) -> void: elif _intersect: operation = 2 - var params := {"color": color, "similarity_percent": _similarity, "operation": operation} + var params := {"color": color, "tolerance": _tolerance, "operation": operation} if _add or _subtract or _intersect: var selection_tex := ImageTexture.create_from_image(project.selection_map) params["selection"] = selection_tex diff --git a/src/Tools/SelectionTools/ColorSelect.tscn b/src/Tools/SelectionTools/ColorSelect.tscn index 58a404bd7..54b9c6c4c 100644 --- a/src/Tools/SelectionTools/ColorSelect.tscn +++ b/src/Tools/SelectionTools/ColorSelect.tscn @@ -2,16 +2,24 @@ [ext_resource type="PackedScene" uid="uid://bd62qfjn380wf" path="res://src/Tools/BaseSelectionTool.tscn" id="1"] [ext_resource type="Script" path="res://src/Tools/SelectionTools/ColorSelect.gd" id="2"] -[ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/ValueSlider.tscn" id="3"] +[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="3_44rxy"] [node name="ToolOptions" instance=ExtResource("1")] script = ExtResource("2") -[node name="SimilaritySlider" parent="." index="9" instance=ExtResource("3")] +[node name="ToleranceSlider" type="TextureProgressBar" parent="." index="8"] +custom_minimum_size = Vector2(32, 24) layout_mode = 2 focus_mode = 2 +mouse_default_cursor_shape = 2 theme_type_variation = &"ValueSlider" -value = 100.0 -prefix = "Similarity:" +max_value = 255.0 +nine_patch_stretch = true +stretch_margin_left = 3 +stretch_margin_top = 3 +stretch_margin_right = 3 +stretch_margin_bottom = 3 +script = ExtResource("3_44rxy") +prefix = "Tolerance:" -[connection signal="value_changed" from="SimilaritySlider" to="." method="_on_Similarity_value_changed"] +[connection signal="value_changed" from="ToleranceSlider" to="." method="_on_tolerance_slider_value_changed"] diff --git a/src/Tools/SelectionTools/MagicWand.gd b/src/Tools/SelectionTools/MagicWand.gd index 43945deae..9e9d6d230 100644 --- a/src/Tools/SelectionTools/MagicWand.gd +++ b/src/Tools/SelectionTools/MagicWand.gd @@ -4,6 +4,7 @@ extends BaseSelectionTool var _allegro_flood_segments: Array[Segment] ## Results array per image while flooding var _allegro_image_segments: Array[Segment] +var _tolerance := 0.003 class Segment: @@ -42,6 +43,22 @@ func apply_selection(pos: Vector2i) -> void: Global.canvas.selection.commit_undo("Select", undo_data) +func get_config() -> Dictionary: + var config := super.get_config() + config["tolerance"] = _tolerance + return config + + +func set_config(config: Dictionary) -> void: + super.set_config(config) + _tolerance = config.get("tolerance", _tolerance) + + +func update_config() -> void: + super.update_config() + $ToleranceSlider.value = _tolerance * 255.0 + + # Add a new segment to the array func _add_new_segment(y := 0) -> void: _allegro_flood_segments.append(Segment.new(y)) @@ -55,13 +72,16 @@ func _flood_line_around_point( ) -> 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): + if not DrawingAlgos.similar_colors(image.get_pixelv(pos), src_color, _tolerance): return pos.x + 1 var west := pos var east := pos - while west.x >= 0 && image.get_pixelv(west).is_equal_approx(src_color): + while west.x >= 0 && DrawingAlgos.similar_colors(image.get_pixelv(west), src_color, _tolerance): west += Vector2i.LEFT - while east.x < project.size.x && image.get_pixelv(east).is_equal_approx(src_color): + while ( + east.x < project.size.x + && DrawingAlgos.similar_colors(image.get_pixelv(east), src_color, _tolerance) + ): east += Vector2i.RIGHT # Make a note of the stuff we processed var c := pos.y @@ -179,3 +199,9 @@ func _set_bit(p: Vector2i, selection_map: SelectionMap, prev_selection_map: Sele selection_map.select_pixel(p, prev_selection_map.is_pixel_selected(p)) else: selection_map.select_pixel(p, !_subtract) + + +func _on_tolerance_slider_value_changed(value: float) -> void: + _tolerance = value / 255.0 + update_config() + save_config() diff --git a/src/Tools/SelectionTools/MagicWand.tscn b/src/Tools/SelectionTools/MagicWand.tscn index 827220847..70705eb1e 100644 --- a/src/Tools/SelectionTools/MagicWand.tscn +++ b/src/Tools/SelectionTools/MagicWand.tscn @@ -1,7 +1,25 @@ -[gd_scene load_steps=3 format=3 uid="uid://blt8u6nvg1k3g"] +[gd_scene load_steps=4 format=3 uid="uid://blt8u6nvg1k3g"] [ext_resource type="PackedScene" uid="uid://bd62qfjn380wf" path="res://src/Tools/BaseSelectionTool.tscn" id="1"] [ext_resource type="Script" path="res://src/Tools/SelectionTools/MagicWand.gd" id="2"] +[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="3_4ed6a"] [node name="ToolOptions" instance=ExtResource("1")] script = ExtResource("2") + +[node name="ToleranceSlider" type="TextureProgressBar" parent="." index="8"] +custom_minimum_size = Vector2(32, 24) +layout_mode = 2 +focus_mode = 2 +mouse_default_cursor_shape = 2 +theme_type_variation = &"ValueSlider" +max_value = 255.0 +nine_patch_stretch = true +stretch_margin_left = 3 +stretch_margin_top = 3 +stretch_margin_right = 3 +stretch_margin_bottom = 3 +script = ExtResource("3_4ed6a") +prefix = "Tolerance:" + +[connection signal="value_changed" from="ToleranceSlider" to="." method="_on_tolerance_slider_value_changed"]