diff --git a/Translations/Translations.pot b/Translations/Translations.pot index b9042f22f..5b0821833 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -1865,6 +1865,10 @@ msgstr "" msgid "Fills the drawn shape with color, instead of drawing a hollow shape" msgstr "" +#. Found in the tool options of the Pencil, Eraser and Shading tools. It is a percentage of how dense the brush is. 100% density means that the brush gets completely drawn, anything less leaves gaps inside the brush, acting like a spray tool. +msgid "Density:" +msgstr "" + msgid "Brush color from" msgstr "" diff --git a/src/Tools/BaseDraw.gd b/src/Tools/BaseDraw.gd index 29b673173..613051b57 100644 --- a/src/Tools/BaseDraw.gd +++ b/src/Tools/BaseDraw.gd @@ -1,8 +1,11 @@ extends BaseTool +const IMAGE_BRUSHES := [Brushes.FILE, Brushes.RANDOM_FILE, Brushes.CUSTOM] + var _brush := Brushes.get_default_brush() var _brush_size := 1 var _brush_size_dynamics := 1 +var _brush_density := 100 var _brush_flip_x := false var _brush_flip_y := false var _brush_rotate_90 := false @@ -89,6 +92,12 @@ func _reset_dynamics() -> void: save_config() +func _on_density_value_slider_value_changed(value: int) -> void: + _brush_density = value + update_config() + save_config() + + func _on_InterpolateFactor_value_changed(value: float) -> void: _brush_interpolate = int(value) update_config() @@ -111,6 +120,7 @@ func get_config() -> Dictionary: "brush_type": _brush.type, "brush_index": _brush.index, "brush_size": _brush_size, + "brush_density": _brush_density, "brush_interpolate": _brush_interpolate, "brush_flip_x": _brush_flip_x, "brush_flip_y": _brush_flip_y, @@ -128,6 +138,7 @@ func set_config(config: Dictionary) -> void: _brush_size_dynamics = _brush_size if Tools.dynamics_size != Tools.Dynamics.NONE: _brush_size_dynamics = Tools.brush_size_min + _brush_density = config.get("brush_density", _brush_density) _brush_interpolate = config.get("brush_interpolate", _brush_interpolate) _brush_flip_x = config.get("brush_flip_x", _brush_flip_x) _brush_flip_y = config.get("brush_flip_y", _brush_flip_y) @@ -181,8 +192,9 @@ func update_brush() -> void: _indicator = _create_brush_indicator() _polylines = _create_polylines(_indicator) $Brush/Type/Texture.texture = _brush_texture - $ColorInterpolation.visible = _brush.type in [Brushes.FILE, Brushes.RANDOM_FILE, Brushes.CUSTOM] - $RotationOptions.visible = _brush.type in [Brushes.FILE, Brushes.RANDOM_FILE, Brushes.CUSTOM] + $DensityValueSlider.visible = _brush.type not in IMAGE_BRUSHES + $ColorInterpolation.visible = _brush.type in IMAGE_BRUSHES + $RotationOptions.visible = _brush.type in IMAGE_BRUSHES func update_random_image() -> void: @@ -492,7 +504,7 @@ func draw_indicator(left: bool) -> void: func draw_indicator_at(pos: Vector2i, offset: Vector2i, color: Color) -> void: var canvas: Node2D = Global.canvas.indicators - if _brush.type in [Brushes.FILE, Brushes.RANDOM_FILE, Brushes.CUSTOM] and not _draw_line: + if _brush.type in IMAGE_BRUSHES and not _draw_line: pos -= _brush_image.get_size() / 2 pos -= offset canvas.draw_texture(_brush_texture, pos) @@ -522,6 +534,8 @@ func _set_pixel(pos: Vector2i, ignore_mirroring := false) -> void: func _set_pixel_no_cache(pos: Vector2i, ignore_mirroring := false) -> void: + if randi() % 100 >= _brush_density: + return pos = _stroke_project.tiles.get_canon_position(pos) if Global.current_project.has_selection: pos = Global.current_project.selection_map.get_canon_position(pos) diff --git a/src/Tools/BaseDraw.tscn b/src/Tools/BaseDraw.tscn index fc6872696..456649af8 100644 --- a/src/Tools/BaseDraw.tscn +++ b/src/Tools/BaseDraw.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=8 format=3 uid="uid://ubyatap3sylf"] +[gd_scene load_steps=9 format=3 uid="uid://ubyatap3sylf"] [ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/ValueSlider.tscn" id="1"] [ext_resource type="PackedScene" uid="uid://ctfgfelg0sho8" path="res://src/Tools/BaseTool.tscn" id="2"] [ext_resource type="Script" path="res://src/Tools/BaseDraw.gd" id="3"] [ext_resource type="Script" path="res://src/UI/Nodes/CollapsibleContainer.gd" id="3_76bek"] +[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="5_kdxku"] [sub_resource type="ButtonGroup" id="ButtonGroup_7u3x0"] resource_name = "rotate" @@ -130,7 +131,24 @@ suffix = "px" global_increment_action = "brush_size_increment" global_decrement_action = "brush_size_decrement" -[node name="ColorInterpolation" parent="." index="4" instance=ExtResource("1")] +[node name="DensityValueSlider" type="TextureProgressBar" parent="." index="4"] +custom_minimum_size = Vector2(0, 24) +layout_mode = 2 +focus_mode = 2 +mouse_default_cursor_shape = 2 +theme_type_variation = &"ValueSlider" +min_value = 1.0 +value = 100.0 +nine_patch_stretch = true +stretch_margin_left = 3 +stretch_margin_top = 3 +stretch_margin_right = 3 +stretch_margin_bottom = 3 +script = ExtResource("5_kdxku") +prefix = "Density:" +suffix = "%" + +[node name="ColorInterpolation" parent="." index="5" instance=ExtResource("1")] visible = false layout_mode = 2 tooltip_text = "0: Color from the brush itself, 100: the currently selected color" @@ -143,4 +161,5 @@ prefix = "Brush color from:" [connection signal="toggled" from="RotationOptions/GridContainer/Rotate/Rotate270" to="." method="_on_rotate_270_toggled"] [connection signal="pressed" from="Brush/Type" to="." method="_on_BrushType_pressed"] [connection signal="value_changed" from="Brush/BrushSize" to="." method="_on_BrushSize_value_changed"] +[connection signal="value_changed" from="DensityValueSlider" to="." method="_on_density_value_slider_value_changed"] [connection signal="value_changed" from="ColorInterpolation" to="." method="_on_InterpolateFactor_value_changed"]