diff --git a/src/Autoload/Tools.gd b/src/Autoload/Tools.gd index 6af417bec..6d4f09a55 100644 --- a/src/Autoload/Tools.gd +++ b/src/Autoload/Tools.gd @@ -1,6 +1,7 @@ extends Node signal color_changed(color: Color, button: int) +signal flip_rotated(flip_x, flip_y, rotate_90, rotate_180, rotate_270) enum Dynamics { NONE, PRESSURE, VELOCITY } diff --git a/src/Tools/BaseDraw.gd b/src/Tools/BaseDraw.gd index 87c954184..6c8729bc2 100644 --- a/src/Tools/BaseDraw.gd +++ b/src/Tools/BaseDraw.gd @@ -3,6 +3,11 @@ extends BaseTool var _brush := Brushes.get_default_brush() var _brush_size := 1 var _brush_size_dynamics := 1 +var _brush_flip_x := false +var _brush_flip_y := false +var _brush_rotate_90 := false +var _brush_rotate_180 := false +var _brush_rotate_270 := false var _cache_limit := 3 var _brush_interpolate := 0 var _brush_image := Image.new() @@ -54,6 +59,9 @@ func _on_BrushType_pressed() -> void: if child is GridContainer: child.columns = columns Global.brushes_popup.popup(Rect2(pop_position, Vector2(size_x, size_y))) + Tools.flip_rotated.emit( + _brush_flip_x, _brush_flip_y, _brush_rotate_90, _brush_rotate_180, _brush_rotate_270 + ) func _on_Brush_selected(brush: Brushes.Brush) -> void: @@ -122,6 +130,11 @@ func set_config(config: Dictionary) -> void: func update_config() -> void: $Brush/BrushSize.value = _brush_size $ColorInterpolation.value = _brush_interpolate + $RotationOptions/Flip/FlipX.button_pressed = _brush_flip_x + $RotationOptions/Flip/FlipY.button_pressed = _brush_flip_y + $RotationOptions/Rotate/Rotate90.button_pressed = _brush_rotate_90 + $RotationOptions/Rotate/Rotate180.button_pressed = _brush_rotate_180 + $RotationOptions/Rotate/Rotate270.button_pressed = _brush_rotate_270 update_brush() @@ -151,6 +164,7 @@ func update_brush() -> void: var random := randi() % _brush.random.size() _orignal_brush_image = _brush.random[random] _brush_image = _create_blended_brush_image(_orignal_brush_image) + update_brush_image_flip_and_rotate() _brush_texture = ImageTexture.create_from_image(_brush_image) update_mirror_brush() _stroke_dimensions = _brush_image.get_size() @@ -158,6 +172,7 @@ func update_brush() -> void: _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] func update_random_image() -> void: @@ -166,6 +181,7 @@ func update_random_image() -> void: var random := randi() % _brush.random.size() _brush_image = _create_blended_brush_image(_brush.random[random]) _orignal_brush_image = _brush_image + update_brush_image_flip_and_rotate() _brush_texture = ImageTexture.create_from_image(_brush_image) _indicator = _create_brush_indicator() update_mirror_brush() @@ -180,6 +196,19 @@ func update_mirror_brush() -> void: _mirror_brushes.xy.flip_y() +func update_brush_image_flip_and_rotate() -> void: + if _brush_flip_x == true: + _brush_image.flip_x() + if _brush_flip_y == true: + _brush_image.flip_y() + if _brush_rotate_90 == true: + _brush_image.rotate_90(CLOCKWISE) + if _brush_rotate_180 == true: + _brush_image.rotate_180() + if _brush_rotate_270 == true: + _brush_image.rotate_90(COUNTERCLOCKWISE) + + func update_mask(can_skip := true) -> void: if can_skip and Tools.dynamics_alpha == Tools.Dynamics.NONE: if _mask: @@ -241,6 +270,7 @@ func draw_end(pos: Vector2i) -> void: match _brush.type: Brushes.FILE, Brushes.RANDOM_FILE, Brushes.CUSTOM: _brush_image = _create_blended_brush_image(_orignal_brush_image) + update_brush_image_flip_and_rotate() _brush_texture = ImageTexture.create_from_image(_brush_image) update_mirror_brush() _stroke_dimensions = _brush_image.get_size() @@ -279,6 +309,7 @@ func _prepare_tool() -> void: Brushes.FILE, Brushes.RANDOM_FILE, Brushes.CUSTOM: # save _brush_image for safe keeping _brush_image = _create_blended_brush_image(_orignal_brush_image) + update_brush_image_flip_and_rotate() _brush_texture = ImageTexture.create_from_image(_brush_image) update_mirror_brush() _stroke_dimensions = _brush_image.get_size() @@ -707,3 +738,28 @@ func _pick_color(pos: Vector2i) -> void: else MOUSE_BUTTON_RIGHT ) Tools.assign_color(color, button, false) + + +func _on_flip_x_toggled(button_pressed: bool) -> void: + _brush_flip_x = button_pressed + update_brush() + + +func _on_flip_y_toggled(button_pressed: bool) -> void: + _brush_flip_y = button_pressed + update_brush() + + +func _on_rotate_90_toggled(button_pressed: bool) -> void: + _brush_rotate_90 = button_pressed + update_brush() + + +func _on_rotate_180_toggled(button_pressed: bool) -> void: + _brush_rotate_180 = button_pressed + update_brush() + + +func _on_rotate_270_toggled(button_pressed: bool) -> void: + _brush_rotate_270 = button_pressed + update_brush() diff --git a/src/Tools/BaseDraw.tscn b/src/Tools/BaseDraw.tscn index b05261e56..cb625adcb 100644 --- a/src/Tools/BaseDraw.tscn +++ b/src/Tools/BaseDraw.tscn @@ -1,8 +1,13 @@ -[gd_scene load_steps=6 format=3 uid="uid://ubyatap3sylf"] +[gd_scene load_steps=8 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"] + +[sub_resource type="ButtonGroup" id="ButtonGroup_7u3x0"] +resource_name = "rotate" +allow_unpress = true [sub_resource type="StyleBoxFlat" id="1"] bg_color = Color(1, 1, 1, 1) @@ -25,7 +30,54 @@ anti_aliasing = false [node name="ToolOptions" instance=ExtResource("2")] script = ExtResource("3") -[node name="Brush" type="HBoxContainer" parent="." index="2"] +[node name="RotationOptions" type="VBoxContainer" parent="." index="2"] +visible = false +layout_mode = 2 +theme_type_variation = &"CollapsibleContainer" +script = ExtResource("3_76bek") +text = "Rotation options" +flat = true + +[node name="Flip" type="HBoxContainer" parent="RotationOptions" index="1"] +visible = false +layout_mode = 2 + +[node name="FlipX" type="CheckBox" parent="RotationOptions/Flip" index="0"] +layout_mode = 2 +mouse_default_cursor_shape = 2 +text = "Flip X" + +[node name="FlipY" type="CheckBox" parent="RotationOptions/Flip" index="1"] +layout_mode = 2 +mouse_default_cursor_shape = 2 +text = "Flip Y" + +[node name="Rotate" type="HBoxContainer" parent="RotationOptions" index="2"] +visible = false +layout_mode = 2 + +[node name="Rotate90" type="CheckBox" parent="RotationOptions/Rotate" index="0"] +layout_mode = 2 +tooltip_text = "rotate the brush 90 degrees" +mouse_default_cursor_shape = 2 +button_group = SubResource("ButtonGroup_7u3x0") +text = "R 90" + +[node name="Rotate180" type="CheckBox" parent="RotationOptions/Rotate" index="1"] +layout_mode = 2 +tooltip_text = "rotate the brush 180 degrees" +mouse_default_cursor_shape = 2 +button_group = SubResource("ButtonGroup_7u3x0") +text = "R 180" + +[node name="Rotate270" type="CheckBox" parent="RotationOptions/Rotate" index="2"] +layout_mode = 2 +tooltip_text = "rotate the brush 270 degrees" +mouse_default_cursor_shape = 2 +button_group = SubResource("ButtonGroup_7u3x0") +text = "R 270" + +[node name="Brush" type="HBoxContainer" parent="." index="3"] layout_mode = 2 alignment = 1 @@ -59,12 +111,17 @@ suffix = "px" global_increment_action = "brush_size_increment" global_decrement_action = "brush_size_decrement" -[node name="ColorInterpolation" parent="." index="3" instance=ExtResource("1")] +[node name="ColorInterpolation" parent="." index="4" instance=ExtResource("1")] visible = false layout_mode = 2 tooltip_text = "0: Color from the brush itself, 100: the currently selected color" prefix = "Brush color from:" +[connection signal="toggled" from="RotationOptions/Flip/FlipX" to="." method="_on_flip_x_toggled"] +[connection signal="toggled" from="RotationOptions/Flip/FlipY" to="." method="_on_flip_y_toggled"] +[connection signal="toggled" from="RotationOptions/Rotate/Rotate90" to="." method="_on_rotate_90_toggled"] +[connection signal="toggled" from="RotationOptions/Rotate/Rotate180" to="." method="_on_rotate_180_toggled"] +[connection signal="toggled" from="RotationOptions/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="ColorInterpolation" to="." method="_on_InterpolateFactor_value_changed"] diff --git a/src/Tools/DesignTools/EllipseTool.tscn b/src/Tools/DesignTools/EllipseTool.tscn index 73e036658..59f20adee 100644 --- a/src/Tools/DesignTools/EllipseTool.tscn +++ b/src/Tools/DesignTools/EllipseTool.tscn @@ -1,7 +1,20 @@ -[gd_scene load_steps=3 format=3 uid="uid://4hp76lf38bc7"] +[gd_scene load_steps=4 format=3 uid="uid://4hp76lf38bc7"] [ext_resource type="PackedScene" uid="uid://n40lhf8hm7o1" path="res://src/Tools/BaseShapeDrawer.tscn" id="1"] [ext_resource type="Script" path="res://src/Tools/DesignTools/EllipseTool.gd" id="2"] +[sub_resource type="ButtonGroup" id="ButtonGroup_q7ttl"] +resource_name = "rotate" +allow_unpress = true + [node name="ToolOptions" instance=ExtResource("1")] script = ExtResource("2") + +[node name="Rotate90" parent="RotationOptions/Rotate" index="0"] +button_group = SubResource("ButtonGroup_q7ttl") + +[node name="Rotate180" parent="RotationOptions/Rotate" index="1"] +button_group = SubResource("ButtonGroup_q7ttl") + +[node name="Rotate270" parent="RotationOptions/Rotate" index="2"] +button_group = SubResource("ButtonGroup_q7ttl") diff --git a/src/Tools/DesignTools/Eraser.tscn b/src/Tools/DesignTools/Eraser.tscn index 1a8354f47..f161245e0 100644 --- a/src/Tools/DesignTools/Eraser.tscn +++ b/src/Tools/DesignTools/Eraser.tscn @@ -1,16 +1,27 @@ -[gd_scene load_steps=4 format=3 uid="uid://btmbrqqig7wys"] +[gd_scene load_steps=5 format=3 uid="uid://btmbrqqig7wys"] [ext_resource type="PackedScene" uid="uid://ubyatap3sylf" path="res://src/Tools/BaseDraw.tscn" id="1"] [ext_resource type="Script" path="res://src/Tools/DesignTools/Eraser.gd" id="2"] [ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/ValueSlider.tscn" id="3"] +[sub_resource type="ButtonGroup" id="ButtonGroup_kkavr"] +resource_name = "rotate" +allow_unpress = true + [node name="ToolOptions" instance=ExtResource("1")] script = ExtResource("2") -[node name="OpacitySlider" parent="." index="4" instance=ExtResource("3")] +[node name="Rotate90" parent="RotationOptions/Rotate" index="0"] +button_group = SubResource("ButtonGroup_kkavr") + +[node name="Rotate180" parent="RotationOptions/Rotate" index="1"] +button_group = SubResource("ButtonGroup_kkavr") + +[node name="Rotate270" parent="RotationOptions/Rotate" index="2"] +button_group = SubResource("ButtonGroup_kkavr") + +[node name="OpacitySlider" parent="." index="5" instance=ExtResource("3")] layout_mode = 2 -focus_mode = 2 -theme_type_variation = &"ValueSlider" max_value = 255.0 value = 255.0 prefix = "Opacity:" diff --git a/src/Tools/DesignTools/LineTool.tscn b/src/Tools/DesignTools/LineTool.tscn index f10be6fbf..08777f19c 100644 --- a/src/Tools/DesignTools/LineTool.tscn +++ b/src/Tools/DesignTools/LineTool.tscn @@ -1,9 +1,13 @@ -[gd_scene load_steps=4 format=3 uid="uid://ceahf2toaq47l"] +[gd_scene load_steps=5 format=3 uid="uid://ceahf2toaq47l"] [ext_resource type="PackedScene" uid="uid://ubyatap3sylf" path="res://src/Tools/BaseDraw.tscn" id="1"] [ext_resource type="Script" path="res://src/Tools/DesignTools/LineTool.gd" id="2"] [ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/ValueSlider.tscn" id="3"] +[sub_resource type="ButtonGroup" id="ButtonGroup_ko8wf"] +resource_name = "rotate" +allow_unpress = true + [node name="ToolOptions" instance=ExtResource("1")] script = ExtResource("2") @@ -16,7 +20,16 @@ suffix = "px" global_increment_action = "brush_size_increment" global_decrement_action = "brush_size_decrement" -[node name="Brush" parent="." index="3"] +[node name="Rotate90" parent="RotationOptions/Rotate" index="0"] +button_group = SubResource("ButtonGroup_ko8wf") + +[node name="Rotate180" parent="RotationOptions/Rotate" index="1"] +button_group = SubResource("ButtonGroup_ko8wf") + +[node name="Rotate270" parent="RotationOptions/Rotate" index="2"] +button_group = SubResource("ButtonGroup_ko8wf") + +[node name="Brush" parent="." index="4"] visible = false [connection signal="value_changed" from="ThicknessSlider" to="." method="_on_Thickness_value_changed"] diff --git a/src/Tools/DesignTools/Pencil.tscn b/src/Tools/DesignTools/Pencil.tscn index 40ae6992c..af81dc0a4 100644 --- a/src/Tools/DesignTools/Pencil.tscn +++ b/src/Tools/DesignTools/Pencil.tscn @@ -1,29 +1,42 @@ -[gd_scene load_steps=4 format=3 uid="uid://cul5mpy17ebfl"] +[gd_scene load_steps=5 format=3 uid="uid://cul5mpy17ebfl"] [ext_resource type="PackedScene" uid="uid://ubyatap3sylf" path="res://src/Tools/BaseDraw.tscn" id="1"] [ext_resource type="PackedScene" path="res://src/UI/Nodes/ValueSliderV2.tscn" id="2"] [ext_resource type="Script" path="res://src/Tools/DesignTools/Pencil.gd" id="3"] +[sub_resource type="ButtonGroup" id="ButtonGroup_clato"] +resource_name = "rotate" +allow_unpress = true + [node name="ToolOptions" instance=ExtResource("1")] script = ExtResource("3") -[node name="Overwrite" type="CheckBox" parent="." index="4"] +[node name="Rotate90" parent="RotationOptions/Rotate" index="0"] +button_group = SubResource("ButtonGroup_clato") + +[node name="Rotate180" parent="RotationOptions/Rotate" index="1"] +button_group = SubResource("ButtonGroup_clato") + +[node name="Rotate270" parent="RotationOptions/Rotate" index="2"] +button_group = SubResource("ButtonGroup_clato") + +[node name="Overwrite" type="CheckBox" parent="." index="5"] layout_mode = 2 tooltip_text = "Overwrites color instead of blending it. This option is only relevant with colors that are not fully opaque" mouse_default_cursor_shape = 2 text = "Overwrite color" -[node name="FillInside" type="CheckBox" parent="." index="5"] +[node name="FillInside" type="CheckBox" parent="." index="6"] layout_mode = 2 mouse_default_cursor_shape = 2 text = "Fill inside" -[node name="SpacingMode" type="CheckBox" parent="." index="6"] +[node name="SpacingMode" type="CheckBox" parent="." index="7"] layout_mode = 2 mouse_default_cursor_shape = 2 text = "Spacing" -[node name="Spacing" parent="." index="7" instance=ExtResource("2")] +[node name="Spacing" parent="." index="8" instance=ExtResource("2")] visible = false layout_mode = 2 allow_greater = true diff --git a/src/Tools/DesignTools/RectangleTool.tscn b/src/Tools/DesignTools/RectangleTool.tscn index a2aa05834..461bc8e09 100644 --- a/src/Tools/DesignTools/RectangleTool.tscn +++ b/src/Tools/DesignTools/RectangleTool.tscn @@ -1,7 +1,20 @@ -[gd_scene load_steps=3 format=3 uid="uid://dhlab4q2dwu0a"] +[gd_scene load_steps=4 format=3 uid="uid://dhlab4q2dwu0a"] [ext_resource type="PackedScene" uid="uid://n40lhf8hm7o1" path="res://src/Tools/BaseShapeDrawer.tscn" id="1"] [ext_resource type="Script" path="res://src/Tools/DesignTools/RectangleTool.gd" id="2"] +[sub_resource type="ButtonGroup" id="ButtonGroup_cyxrj"] +resource_name = "rotate" +allow_unpress = true + [node name="ToolOptions" instance=ExtResource("1")] script = ExtResource("2") + +[node name="Rotate90" parent="RotationOptions/Rotate" index="0"] +button_group = SubResource("ButtonGroup_cyxrj") + +[node name="Rotate180" parent="RotationOptions/Rotate" index="1"] +button_group = SubResource("ButtonGroup_cyxrj") + +[node name="Rotate270" parent="RotationOptions/Rotate" index="2"] +button_group = SubResource("ButtonGroup_cyxrj") diff --git a/src/Tools/DesignTools/Shading.tscn b/src/Tools/DesignTools/Shading.tscn index 79b731d0d..4b87b3a48 100644 --- a/src/Tools/DesignTools/Shading.tscn +++ b/src/Tools/DesignTools/Shading.tscn @@ -1,13 +1,26 @@ -[gd_scene load_steps=4 format=3 uid="uid://rbyd7i6snxjc"] +[gd_scene load_steps=5 format=3 uid="uid://rbyd7i6snxjc"] [ext_resource type="PackedScene" uid="uid://ubyatap3sylf" path="res://src/Tools/BaseDraw.tscn" id="1"] [ext_resource type="Script" path="res://src/Tools/DesignTools/Shading.gd" id="2"] [ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/ValueSlider.tscn" id="3"] +[sub_resource type="ButtonGroup" id="ButtonGroup_se02m"] +resource_name = "rotate" +allow_unpress = true + [node name="ToolOptions" instance=ExtResource("1")] script = ExtResource("2") -[node name="LightenDarken" type="OptionButton" parent="." index="4"] +[node name="Rotate90" parent="RotationOptions/Rotate" index="0"] +button_group = SubResource("ButtonGroup_se02m") + +[node name="Rotate180" parent="RotationOptions/Rotate" index="1"] +button_group = SubResource("ButtonGroup_se02m") + +[node name="Rotate270" parent="RotationOptions/Rotate" index="2"] +button_group = SubResource("ButtonGroup_se02m") + +[node name="LightenDarken" type="OptionButton" parent="." index="5"] custom_minimum_size = Vector2(92, 0) layout_mode = 2 mouse_default_cursor_shape = 2 @@ -18,7 +31,7 @@ popup/item_0/id = 0 popup/item_1/text = "Darken" popup/item_1/id = 1 -[node name="ShadingMode" type="OptionButton" parent="." index="5"] +[node name="ShadingMode" type="OptionButton" parent="." index="6"] layout_mode = 2 mouse_default_cursor_shape = 2 item_count = 2 @@ -28,37 +41,29 @@ popup/item_0/id = 0 popup/item_1/text = "Hue Shifting" popup/item_1/id = 1 -[node name="AmountSlider" parent="." index="6" instance=ExtResource("3")] +[node name="AmountSlider" parent="." index="7" instance=ExtResource("3")] layout_mode = 2 tooltip_text = "Lighten/Darken amount" -focus_mode = 2 -theme_type_variation = &"ValueSlider" value = 10.0 prefix = "Amount:" -[node name="HueShiftingOptions" type="VBoxContainer" parent="." index="7"] +[node name="HueShiftingOptions" type="VBoxContainer" parent="." index="8"] visible = false layout_mode = 2 [node name="HueSlider" parent="HueShiftingOptions" index="0" instance=ExtResource("3")] layout_mode = 2 -focus_mode = 2 -theme_type_variation = &"ValueSlider" max_value = 180.0 value = 10.0 prefix = "Hue:" [node name="SatSlider" parent="HueShiftingOptions" index="1" instance=ExtResource("3")] layout_mode = 2 -focus_mode = 2 -theme_type_variation = &"ValueSlider" value = 10.0 prefix = "Saturation:" [node name="ValueSlider" parent="HueShiftingOptions" index="2" instance=ExtResource("3")] layout_mode = 2 -focus_mode = 2 -theme_type_variation = &"ValueSlider" value = 10.0 prefix = "Value:" diff --git a/src/UI/Buttons/BrushButton.gd b/src/UI/Buttons/BrushButton.gd index 951e4d41a..02c49904c 100644 --- a/src/UI/Buttons/BrushButton.gd +++ b/src/UI/Buttons/BrushButton.gd @@ -3,6 +3,10 @@ extends BaseButton var brush = Global.brushes_popup.Brush.new() +func _ready() -> void: + Tools.flip_rotated.connect(_flip_rotate_updated) + + func _on_BrushButton_pressed() -> void: # Delete the brush on middle mouse press if Input.is_action_just_released("middle_mouse"): @@ -26,3 +30,18 @@ func _on_BrushButton_mouse_entered() -> void: func _on_BrushButton_mouse_exited() -> void: if brush.type == Global.brushes_popup.CUSTOM: $DeleteButton.visible = false + + +func _flip_rotate_updated( + flip_x: bool, flip_y: bool, rotate_90: bool, rotate_180: bool, rotate_270: bool +): + $BrushTexture.set_flip_h(flip_x) + $BrushTexture.set_flip_v(flip_y) + var brush_texture_rotation = 0 + if rotate_90 == true: + brush_texture_rotation += 90 + if rotate_180 == true: + brush_texture_rotation += 180 + if rotate_270 == true: + brush_texture_rotation += 270 + $BrushTexture.rotation_degrees = brush_texture_rotation diff --git a/src/UI/Buttons/BrushButton.tscn b/src/UI/Buttons/BrushButton.tscn index 4df757891..0b278e1be 100644 --- a/src/UI/Buttons/BrushButton.tscn +++ b/src/UI/Buttons/BrushButton.tscn @@ -19,6 +19,7 @@ offset_left = 2.0 offset_top = 2.0 offset_right = -2.0 offset_bottom = -2.0 +pivot_offset = Vector2(16, 16) expand_mode = 1 stretch_mode = 6