diff --git a/Changelog.md b/Changelog.md index ba40d3064..ab805190b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,7 +15,7 @@ Martin Novák (novhack), Darshan Phaldesai (luiq54), Schweini07, Marco Galli (Ga - You can now export your projects to .gif files. - A new rotation method has been added, "Upscale, Rotate and Downscale". It's similar to Rotsprite. - An HSV Adjust dialog has been added in the Images menu. -- Pattern filling is now possible. If the user chooses a brush that is not the pixel or a circle brush and uses the bucket tool, the brush image is used as a pattern that fills the area. +- Pattern filling is now possible. The bucket tool can now use Patterns to fill areas, instead of a single color. - Users can now change keyboard shortcut bindings for tools, in the Preferences. - Importing .pngs as palettes is now possible. - A confirmation message now appears when the user quits Pixelorama, if there are unsaved changes. diff --git a/Main.tscn b/Main.tscn index 62044dc09..400c1fd61 100644 --- a/Main.tscn +++ b/Main.tscn @@ -677,13 +677,13 @@ ticks_on_borders = true [node name="LeftFillArea" type="VBoxContainer" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions"] visible = false -margin_top = 75.0 -margin_right = 159.0 -margin_bottom = 117.0 +margin_top = 71.0 +margin_right = 160.0 +margin_bottom = 155.0 [node name="FillAreaLabel" type="Label" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea"] -margin_left = 56.0 -margin_right = 102.0 +margin_left = 57.0 +margin_right = 103.0 margin_bottom = 15.0 mouse_default_cursor_shape = 2 size_flags_horizontal = 4 @@ -692,8 +692,8 @@ text = "Fill area:" [node name="LeftFillAreaOptions" type="OptionButton" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea"] margin_left = 24.0 margin_top = 19.0 -margin_right = 134.0 -margin_bottom = 42.0 +margin_right = 136.0 +margin_bottom = 40.0 focus_mode = 0 mouse_default_cursor_shape = 2 size_flags_horizontal = 4 @@ -701,6 +701,50 @@ text = "Same color area" items = [ "Same color area", null, false, 0, null, "Same color pixels", null, false, 1, null ] selected = 0 +[node name="FillWithLabel" type="Label" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea"] +margin_left = 57.0 +margin_top = 44.0 +margin_right = 102.0 +margin_bottom = 59.0 +size_flags_horizontal = 4 +text = "Fill with:" + +[node name="LeftFillWithOptions" type="OptionButton" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea"] +margin_left = 42.0 +margin_top = 63.0 +margin_right = 118.0 +margin_bottom = 84.0 +mouse_default_cursor_shape = 2 +size_flags_horizontal = 4 +text = "Selected Color" +items = [ "Selected Color", null, false, 0, null, "Pattern", null, false, 1, null ] +selected = 0 + +[node name="LeftFillPattern" type="VBoxContainer" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea"] +visible = false +margin_left = 59.0 +margin_top = 88.0 +margin_right = 95.0 +margin_bottom = 120.0 +size_flags_horizontal = 4 + +[node name="LeftPatternTypeButton" type="TextureButton" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea/LeftFillPattern"] +margin_right = 36.0 +margin_bottom = 32.0 +rect_min_size = Vector2( 36, 32 ) +hint_tooltip = "Select a brush" +mouse_default_cursor_shape = 2 +texture_normal = ExtResource( 12 ) + +[node name="PatternTexture" type="TextureRect" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea/LeftFillPattern/LeftPatternTypeButton"] +margin_right = 32.0 +margin_bottom = 32.0 +expand = true +stretch_mode = 6 +__meta__ = { +"_edit_use_anchors_": false +} + [node name="LeftLDOptions" type="VBoxContainer" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions"] visible = false margin_top = 75.0 @@ -987,22 +1031,22 @@ ticks_on_borders = true [node name="RightFillArea" type="VBoxContainer" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions"] visible = false -margin_top = 75.0 -margin_right = 144.0 -margin_bottom = 117.0 +margin_top = 71.0 +margin_right = 160.0 +margin_bottom = 155.0 [node name="FillAreaLabel" type="Label" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea"] -margin_left = 49.0 -margin_right = 95.0 +margin_left = 57.0 +margin_right = 103.0 margin_bottom = 15.0 size_flags_horizontal = 4 text = "Fill area:" [node name="RightFillAreaOptions" type="OptionButton" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea"] -margin_left = 17.0 +margin_left = 24.0 margin_top = 19.0 -margin_right = 127.0 -margin_bottom = 42.0 +margin_right = 136.0 +margin_bottom = 40.0 focus_mode = 0 mouse_default_cursor_shape = 2 size_flags_horizontal = 4 @@ -1010,6 +1054,50 @@ text = "Same color area" items = [ "Same color area", null, false, 0, null, "Same color pixels", null, false, 1, null ] selected = 0 +[node name="FillWithLabel" type="Label" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea"] +margin_left = 57.0 +margin_top = 44.0 +margin_right = 102.0 +margin_bottom = 59.0 +size_flags_horizontal = 4 +text = "Fill with:" + +[node name="RightFillWithOptions" type="OptionButton" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea"] +margin_left = 38.0 +margin_top = 63.0 +margin_right = 122.0 +margin_bottom = 84.0 +mouse_default_cursor_shape = 2 +size_flags_horizontal = 4 +text = "Selected Color" +items = [ "Selected Color", null, false, 0, null, "Pattern", null, false, 1, null ] +selected = 0 + +[node name="RightFillPattern" type="VBoxContainer" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea"] +visible = false +margin_left = 59.0 +margin_top = 88.0 +margin_right = 95.0 +margin_bottom = 120.0 +size_flags_horizontal = 4 + +[node name="RightPatternTypeButton" type="TextureButton" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea/RightFillPattern"] +margin_right = 36.0 +margin_bottom = 32.0 +rect_min_size = Vector2( 36, 32 ) +hint_tooltip = "Select a brush" +mouse_default_cursor_shape = 2 +texture_normal = ExtResource( 12 ) + +[node name="PatternTexture" type="TextureRect" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea/RightFillPattern/RightPatternTypeButton"] +margin_right = 32.0 +margin_bottom = 32.0 +expand = true +stretch_mode = 6 +__meta__ = { +"_edit_use_anchors_": false +} + [node name="RightLDOptions" type="VBoxContainer" parent="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions"] visible = false margin_top = 75.0 @@ -1310,11 +1398,13 @@ columns = 6 [node name="PixelBrushButton" parent="BrushesPopup/TabContainer/File/FileBrushContainer" instance=ExtResource( 26 )] hint_tooltip = "Pixel brush" +mouse_default_cursor_shape = 2 [node name="CircleBrushButton" parent="BrushesPopup/TabContainer/File/FileBrushContainer" instance=ExtResource( 26 )] -margin_left = 32.0 -margin_right = 64.0 +margin_left = 35.0 +margin_right = 67.0 hint_tooltip = "Filled circle brush" +mouse_default_cursor_shape = 2 brush_type = 1 custom_brush_index = -2 @@ -1322,9 +1412,10 @@ custom_brush_index = -2 texture = SubResource( 9 ) [node name="FilledCircleBrushButton" parent="BrushesPopup/TabContainer/File/FileBrushContainer" instance=ExtResource( 26 )] -margin_left = 64.0 -margin_right = 96.0 +margin_left = 70.0 +margin_right = 102.0 hint_tooltip = "Circle brush" +mouse_default_cursor_shape = 2 brush_type = 2 custom_brush_index = -1 @@ -1346,6 +1437,23 @@ scroll_horizontal_enabled = false [node name="ProjectBrushContainer" type="GridContainer" parent="BrushesPopup/TabContainer/Project"] columns = 5 +[node name="PatternsPopup" type="PopupPanel" parent="."] +margin_right = 226.0 +margin_bottom = 104.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ScrollContainer" type="ScrollContainer" parent="PatternsPopup"] +anchor_right = 1.0 +anchor_bottom = 1.0 +rect_min_size = Vector2( 0, 36 ) +size_flags_horizontal = 3 +scroll_horizontal_enabled = false + +[node name="PatternContainer" type="GridContainer" parent="PatternsPopup/ScrollContainer"] +columns = 6 + [node name="SplashDialog" parent="." instance=ExtResource( 27 )] [node name="CreateNewImage" parent="." instance=ExtResource( 28 )] @@ -1358,8 +1466,8 @@ resizable = true mode = 0 access = 2 filters = PoolStringArray( "*.pxo ; Pixelorama Project" ) -current_dir = "E:/Projekty/Godot/Pixelorama" -current_path = "E:/Projekty/Godot/Pixelorama/" +current_dir = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama" +current_path = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama/" [node name="SaveSprite" type="FileDialog" parent="."] anchor_left = 0.5 @@ -1374,13 +1482,11 @@ window_title = "Save Sprite as .pxo" resizable = true access = 2 filters = PoolStringArray( "*.pxo ; Pixelorama Project" ) -current_dir = "E:/Projekty/Godot/Pixelorama" -current_path = "E:/Projekty/Godot/Pixelorama/" +current_dir = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama" +current_path = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama/" [node name="ImportSprites" parent="." instance=ExtResource( 29 )] window_title = "Otwórz plik(i)" -current_dir = "E:/Projekty/Godot/Pixelorama" -current_path = "E:/Projekty/Godot/Pixelorama/" [node name="ExportDialog" parent="." instance=ExtResource( 39 )] @@ -1430,7 +1536,6 @@ dialog_text = "This is an error message!" [node name="PaletteImportFileDialog" parent="." instance=ExtResource( 37 )] window_title = "Otwórz plik" filters = PoolStringArray( "*.json ; JavaScript Object Notation", "*.gpl ; Gimp Palette Library", "*.png; Portable Network Graphics" ) -current_file = "Pixelorama" current_dir = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects" current_path = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/" @@ -1470,6 +1575,8 @@ visible = false [connection signal="value_changed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftColorInterpolation/LeftInterpolateFactor" to="." method="_on_LeftInterpolateFactor_value_changed"] [connection signal="value_changed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftColorInterpolation/LeftInterpolateSlider" to="." method="_on_LeftInterpolateFactor_value_changed"] [connection signal="item_selected" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea/LeftFillAreaOptions" to="." method="_on_LeftFillAreaOptions_item_selected"] +[connection signal="item_selected" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea/LeftFillWithOptions" to="." method="_on_LeftFillWithOptions_item_selected"] +[connection signal="pressed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftFillArea/LeftFillPattern/LeftPatternTypeButton" to="." method="_on_LeftPatternTypeButton_pressed"] [connection signal="item_selected" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftLDOptions/LeftLightenDarken" to="." method="_on_LeftLightenDarken_item_selected"] [connection signal="value_changed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftLDOptions/LeftLDAmountSpinbox" to="." method="_on_LeftLDAmountSpinbox_value_changed"] [connection signal="value_changed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/LeftToolOptions/LeftLDOptions/LeftLDAmountSlider" to="." method="_on_LeftLDAmountSpinbox_value_changed"] @@ -1485,6 +1592,8 @@ visible = false [connection signal="value_changed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightColorInterpolation/RightInterpolateFactor" to="." method="_on_RightInterpolateFactor_value_changed"] [connection signal="value_changed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightColorInterpolation/RightInterpolateSlider" to="." method="_on_RightInterpolateFactor_value_changed"] [connection signal="item_selected" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea/RightFillAreaOptions" to="." method="_on_RightFillAreaOptions_item_selected"] +[connection signal="item_selected" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea/RightFillWithOptions" to="." method="_on_RightFillWithOptions_item_selected"] +[connection signal="pressed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightFillArea/RightFillPattern/RightPatternTypeButton" to="." method="_on_RightPatternTypeButton_pressed"] [connection signal="item_selected" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightLDOptions/RightLightenDarken" to="." method="_on_RightLightenDarken_item_selected"] [connection signal="value_changed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightLDOptions/RightLDAmountSpinbox" to="." method="_on_RightLDAmountSpinbox_value_changed"] [connection signal="value_changed" from="MenuAndUI/UI/RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit/ColorAndToolOptions/ScrollContainer/ToolOptions/RightToolOptions/RightLDOptions/RightLDAmountSlider" to="." method="_on_RightLDAmountSpinbox_value_changed"] diff --git a/Prefabs/PatternButton.gd b/Prefabs/PatternButton.gd new file mode 100644 index 000000000..6e45b4b55 --- /dev/null +++ b/Prefabs/PatternButton.gd @@ -0,0 +1,22 @@ +extends TextureButton + + +var image : Image +var texture : ImageTexture + + +func _ready(): + if image: + texture = ImageTexture.new() + texture.create_from_image(image, 0) + + +func _on_PatternButton_pressed() -> void: + if Global.pattern_window_position == "left": + Global.pattern_left_image = image + Global.left_fill_pattern_container.get_child(0).get_child(0).texture = texture + + elif Global.pattern_window_position == "right": + Global.pattern_right_image = image + Global.right_fill_pattern_container.get_child(0).get_child(0).texture = texture + Global.patterns_popup.hide() diff --git a/Prefabs/PatternButton.tscn b/Prefabs/PatternButton.tscn new file mode 100644 index 000000000..8f2e631f7 --- /dev/null +++ b/Prefabs/PatternButton.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://Assets/Graphics/Brush_button.png" type="Texture" id=1] +[ext_resource path="res://Prefabs/PatternButton.gd" type="Script" id=2] + +[node name="PatternButton" type="TextureButton"] +margin_right = 32.0 +margin_bottom = 32.0 +rect_min_size = Vector2( 3, 0 ) +button_mask = 7 +texture_normal = ExtResource( 1 ) +stretch_mode = 5 +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="PatternTexture" type="TextureRect" parent="."] +margin_right = 32.0 +margin_bottom = 32.0 +rect_min_size = Vector2( 32, 32 ) +expand = true +stretch_mode = 6 +__meta__ = { +"_edit_use_anchors_": false +} +[connection signal="pressed" from="." to="." method="_on_PatternButton_pressed"] diff --git a/Scripts/BrushButton.gd b/Scripts/BrushButton.gd index 8c50be0d0..cfe5db4b4 100644 --- a/Scripts/BrushButton.gd +++ b/Scripts/BrushButton.gd @@ -17,7 +17,7 @@ func _on_BrushButton_pressed() -> void: Global.current_left_brush_type = brush_type Global.custom_left_brush_index = custom_brush_index if custom_brush_index > -1: # Custom brush - if Global.current_left_tool == "Pencil" or Global.current_left_tool == "Bucket": + if Global.current_left_tool == "Pencil": Global.left_color_interpolation_container.visible = true # if hint_tooltip == "": # Global.left_brush_type_label.text = tr("Custom brush") @@ -40,7 +40,7 @@ func _on_BrushButton_pressed() -> void: Global.current_right_brush_type = brush_type Global.custom_right_brush_index = custom_brush_index if custom_brush_index > -1: - if Global.current_right_tool == "Pencil" or Global.current_right_tool == "Bucket": + if Global.current_right_tool == "Pencil": Global.right_color_interpolation_container.visible = true # if hint_tooltip == "": # Global.right_brush_type_label.text = tr("Custom brush") diff --git a/Scripts/Canvas.gd b/Scripts/Canvas.gd index caea3965b..eaaeedefc 100644 --- a/Scripts/Canvas.gd +++ b/Scripts/Canvas.gd @@ -338,19 +338,14 @@ func _input(event : InputEvent) -> void: pencil_and_eraser(sprite, mouse_pos, Color(0, 0, 0, 0), current_mouse_button, current_action) "Bucket": if can_handle: - var brush_type = Global.Brush_Types.PIXEL - var custom_brush_image : Image - var is_custom_brush := false + var fill_with := 0 + var pattern_image : Image if current_mouse_button == "left_mouse": - brush_type = Global.current_left_brush_type - is_custom_brush = brush_type == Global.Brush_Types.FILE or brush_type == Global.Brush_Types.CUSTOM or brush_type == Global.Brush_Types.RANDOM_FILE - if is_custom_brush: - custom_brush_image = Global.custom_left_brush_image + fill_with = Global.left_fill_with + pattern_image = Global.pattern_left_image elif current_mouse_button == "right_mouse": - brush_type = Global.current_right_brush_type - is_custom_brush = brush_type == Global.Brush_Types.FILE or brush_type == Global.Brush_Types.CUSTOM or brush_type == Global.Brush_Types.RANDOM_FILE - if is_custom_brush: - custom_brush_image = Global.custom_right_brush_image + fill_with = Global.right_fill_with + pattern_image = Global.pattern_right_image if fill_area == 0: # Paint the specific area of the same color var horizontal_mirror := false @@ -364,17 +359,17 @@ func _input(event : InputEvent) -> void: horizontal_mirror = Global.right_horizontal_mirror vertical_mirror = Global.right_vertical_mirror - if is_custom_brush: # Pattern fill - pattern_fill(sprite, mouse_pos, custom_brush_image, sprite.get_pixelv(mouse_pos)) + if fill_with == 1: # Pattern fill + pattern_fill(sprite, mouse_pos, pattern_image, sprite.get_pixelv(mouse_pos)) if horizontal_mirror: var pos := Vector2(mirror_x, mouse_pos.y) - pattern_fill(sprite, pos, custom_brush_image, sprite.get_pixelv(mouse_pos)) + pattern_fill(sprite, pos, pattern_image, sprite.get_pixelv(mouse_pos)) if vertical_mirror: var pos := Vector2(mouse_pos.x, mirror_y) - pattern_fill(sprite, pos, custom_brush_image, sprite.get_pixelv(mouse_pos)) + pattern_fill(sprite, pos, pattern_image, sprite.get_pixelv(mouse_pos)) if horizontal_mirror && vertical_mirror: var pos := Vector2(mirror_x, mirror_y) - pattern_fill(sprite, pos, custom_brush_image, sprite.get_pixelv(mouse_pos)) + pattern_fill(sprite, pos, pattern_image, sprite.get_pixelv(mouse_pos)) else: # Flood fill flood_fill(sprite, mouse_pos, sprite.get_pixelv(mouse_pos), current_color) if horizontal_mirror: @@ -393,14 +388,14 @@ func _input(event : InputEvent) -> void: for yy in range(north_limit, south_limit): var c : Color = sprite.get_pixel(xx, yy) if c == pixel_color: - if is_custom_brush: # Pattern fill - custom_brush_image.lock() - var pattern_size := custom_brush_image.get_size() + if fill_with == 1: # Pattern fill + pattern_image.lock() + var pattern_size := pattern_image.get_size() var xxx : int = int(xx) % int(pattern_size.x) var yyy : int = int(yy) % int(pattern_size.y) - var pattern_color : Color = custom_brush_image.get_pixel(xxx, yyy) + var pattern_color : Color = pattern_image.get_pixel(xxx, yyy) sprite.set_pixel(xx, yy, pattern_color) - custom_brush_image.unlock() + pattern_image.unlock() else: sprite.set_pixel(xx, yy, current_color) sprite_changed_this_frame = true diff --git a/Scripts/Dialogs/SplashDialog.gd b/Scripts/Dialogs/SplashDialog.gd index 37099130e..a2d2063b7 100644 --- a/Scripts/Dialogs/SplashDialog.gd +++ b/Scripts/Dialogs/SplashDialog.gd @@ -13,7 +13,7 @@ func _on_SplashDialog_about_to_show() -> void: var current_version : String = ProjectSettings.get_setting("application/config/Version") window_title = "Pixelorama" + " " + current_version changes_label.text = current_version + " " + tr("Changes") - developed_by_label.text = "Pixelorama" + " " + current_version + " - " + tr("MADEBY_LABEL") + developed_by_label.text = "Pixelorama" + " " + current_version + " - " + tr("Developed by Orama Interactive") art_by_label.text = tr("Art by") + ": Erevos" if "zh" in TranslationServer.get_locale(): diff --git a/Scripts/Global.gd b/Scripts/Global.gd index f23558f67..a26cba4b8 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -27,8 +27,6 @@ enum Direction { # that direction has been pressed. var key_move_press_time := [0.0, 0.0, 0.0, 0.0] - -# warning-ignore:unused_class_variable var loaded_locales : Array var undo_redo : UndoRedo var undos := 0 # The number of times we added undo properties @@ -40,9 +38,9 @@ var layers := [] setget layers_changed var layers_changed_skip := false var current_frame := 0 setget frame_changed var current_layer := 0 setget layer_changed -# warning-ignore:unused_class_variable + var can_draw := false -# warning-ignore:unused_class_variable + var has_focus := false var pressure_sensitivity_mode = Pressure_Sensitivity.NONE var open_last_project := true @@ -50,139 +48,99 @@ var smooth_zoom := true var cursor_image = preload("res://Assets/Graphics/Cursor.png") var left_cursor_tool_texture : ImageTexture var right_cursor_tool_texture : ImageTexture -# warning-ignore:unused_class_variable + var selected_pixels := [] var image_clipboard : Image var animation_tags := [] setget animation_tags_changed # [Name, Color, From, To] var play_only_tags := true -# warning-ignore:unused_class_variable var theme_type := "Dark" -# warning-ignore:unused_class_variable var is_default_image := true -# warning-ignore:unused_class_variable var default_image_width := 64 -# warning-ignore:unused_class_variable var default_image_height := 64 -# warning-ignore:unused_class_variable var default_fill_color := Color(0, 0, 0, 0) var grid_type = Grid_Types.CARTESIAN -# warning-ignore:unused_class_variable var grid_width := 1 -# warning-ignore:unused_class_variable var grid_height := 1 -# warning-ignore:unused_class_variable var grid_color := Color.black -# warning-ignore:unused_class_variable var guide_color := Color.purple -# warning-ignore:unused_class_variable var checker_size := 10 -# warning-ignore:unused_class_variable var checker_color_1 := Color.gray -# warning-ignore:unused_class_variable var checker_color_2 := Color.white # Tools & options -# warning-ignore:unused_class_variable var current_left_tool := "Pencil" -# warning-ignore:unused_class_variable var current_right_tool := "Eraser" -# warning-ignore:unused_class_variable var show_left_tool_icon := true -# warning-ignore:unused_class_variable var show_right_tool_icon := true -# warning-ignore:unused_class_variable var left_square_indicator_visible := true -# warning-ignore:unused_class_variable var right_square_indicator_visible := false -#0 for area of same color, 1 for all pixels of the same color -# warning-ignore:unused_class_variable + +# 0 for area of same color, 1 for all pixels of the same color var left_fill_area := 0 -# warning-ignore:unused_class_variable var right_fill_area := 0 +var left_fill_with := 0 +var right_fill_with := 0 + # 0 for lighten, 1 for darken -# warning-ignore:unused_class_variable var left_ld := 0 -# warning-ignore:unused_class_variable var right_ld := 0 -# warning-ignore:unused_class_variable var left_ld_amount := 0.1 -# warning-ignore:unused_class_variable var right_ld_amount := 0.1 # 0 for the left, 1 for the right -# warning-ignore:unused_class_variable var left_color_picker_for := 0 -# warning-ignore:unused_class_variable var right_color_picker_for := 1 # 0 for zoom in, 1 for zoom out var left_zoom_mode := 0 var right_zoom_mode := 1 -# warning-ignore:unused_class_variable var left_horizontal_mirror := false -# warning-ignore:unused_class_variable var left_vertical_mirror := false -# warning-ignore:unused_class_variable var right_horizontal_mirror := false -# warning-ignore:unused_class_variable var right_vertical_mirror := false # View menu options -# warning-ignore:unused_class_variable var tile_mode := false -# warning-ignore:unused_class_variable var draw_grid := false -# warning-ignore:unused_class_variable var show_rulers := true -# warning-ignore:unused_class_variable var show_guides := true -# warning-ignore:unused_class_variable var show_animation_timeline := true # Onion skinning options var onion_skinning := false -# warning-ignore:unused_class_variable var onion_skinning_past_rate := 1 -# warning-ignore:unused_class_variable var onion_skinning_future_rate := 1 -# warning-ignore:unused_class_variable var onion_skinning_blue_red := false # Brushes -# warning-ignore:unused_class_variable var left_brush_size := 1 -# warning-ignore:unused_class_variable var right_brush_size := 1 -# warning-ignore:unused_class_variable var current_left_brush_type = Brush_Types.PIXEL -# warning-ignore:unused_class_variable var current_right_brush_type = Brush_Types.PIXEL -# warning-ignore:unused_class_variable + var brush_type_window_position := "left" var left_circle_points := [] var right_circle_points := [] var brushes_from_files := 0 -# warning-ignore:unused_class_variable var custom_brushes := [] -# warning-ignore:unused_class_variable var custom_left_brush_index := -1 -# warning-ignore:unused_class_variable var custom_right_brush_index := -1 -# warning-ignore:unused_class_variable var custom_left_brush_image : Image -# warning-ignore:unused_class_variable var custom_right_brush_image : Image -# warning-ignore:unused_class_variable var custom_left_brush_texture := ImageTexture.new() -# warning-ignore:unused_class_variable var custom_right_brush_texture := ImageTexture.new() +# Patterns +var patterns := [] +var pattern_window_position := "left" +var pattern_left_image : Image +var pattern_right_image : Image + # Palettes -# warning-ignore:unused_class_variable var palettes := {} # Nodes @@ -227,6 +185,7 @@ var right_brush_type_button : BaseButton var brushes_popup : Popup var file_brush_container : GridContainer var project_brush_container : GridContainer +var patterns_popup : Popup var left_brush_size_edit : SpinBox var left_brush_size_slider : HSlider @@ -241,7 +200,9 @@ var right_interpolate_spinbox : SpinBox var right_interpolate_slider : HSlider var left_fill_area_container : Container +var left_fill_pattern_container : Container var right_fill_area_container : Container +var right_fill_pattern_container : Container var left_ld_container : Container var left_ld_amount_slider : HSlider @@ -292,6 +253,7 @@ var palette_import_file_dialog : FileDialog var error_dialog : AcceptDialog + func _ready() -> void: randomize() if OS.has_feature("standalone"): @@ -352,6 +314,7 @@ func _ready() -> void: brushes_popup = find_node_by_name(root, "BrushesPopup") file_brush_container = find_node_by_name(brushes_popup, "FileBrushContainer") project_brush_container = find_node_by_name(brushes_popup, "ProjectBrushContainer") + patterns_popup = find_node_by_name(root, "PatternsPopup") left_brush_size_edit = find_node_by_name(root, "LeftBrushSizeEdit") left_brush_size_slider = find_node_by_name(root, "LeftBrushSizeSlider") @@ -366,7 +329,9 @@ func _ready() -> void: right_interpolate_slider = find_node_by_name(root, "RightInterpolateSlider") left_fill_area_container = find_node_by_name(root, "LeftFillArea") + left_fill_pattern_container = find_node_by_name(root, "LeftFillPattern") right_fill_area_container = find_node_by_name(root, "RightFillArea") + right_fill_pattern_container = find_node_by_name(root, "RightFillPattern") left_ld_container = find_node_by_name(root, "LeftLDOptions") left_ld_amount_slider = find_node_by_name(root, "LeftLDAmountSlider") @@ -838,11 +803,13 @@ func create_brush_button(brush_img : Image, brush_type := Brush_Types.CUSTOM, hi brush_tex.create_from_image(brush_img, 0) brush_button.get_child(0).texture = brush_tex brush_button.hint_tooltip = hint_tooltip + brush_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND brush_button.connect("brush_selected",control,"_on_Brush_Selected") if brush_type == Brush_Types.RANDOM_FILE: brush_button.random_brushes.append(brush_img) brush_container.add_child(brush_button) + func remove_brush_buttons() -> void: current_left_brush_type = Brush_Types.PIXEL current_right_brush_type = Brush_Types.PIXEL diff --git a/Scripts/Import.gd b/Scripts/Import.gd index 336cee1dd..243225101 100644 --- a/Scripts/Import.gd +++ b/Scripts/Import.gd @@ -32,7 +32,6 @@ func get_brush_files_from_directory(directory: String): # -> Array if err != OK: return null - # Build first the list of base png files and all subdirectories to # scan later (skip navigational . and ..) main_directory.list_dir_begin(true) @@ -40,9 +39,8 @@ func get_brush_files_from_directory(directory: String): # -> Array while fname != "": if main_directory.current_is_dir(): subdirectories.append(fname) - else: # Filter for pngs + else: # Filter for pngs if fname.get_extension().to_lower() == "png": - print_debug("Found brush at '%s'" % [fname]) base_png_files.append(fname) # go to next @@ -86,8 +84,7 @@ func get_brush_files_from_directory(directory: String): # -> Array return [base_png_files, randomised_subdir_files_map, nonrandomised_subdir_files_map] -# Add a randomised brush from the given list of files as a -# source. +# Add a randomised brush from the given list of files as a source. # The tooltip name is what shows up on the tooltip # and is probably in this case the name of the containing # randomised directory. @@ -100,7 +97,6 @@ func add_randomised_brush(fpaths : Array, tooltip_name : String) -> void: if err == OK: image.convert(Image.FORMAT_RGBA8) loaded_images.append(image) - print_debug("Loaded image from '%s'" % [filen]) # If any images were successfully loaded, then # we create the randomised brush button, copied @@ -220,40 +216,45 @@ func import_brushes(priority_ordered_search_path: Array) -> void: Global.brushes_from_files = Global.custom_brushes.size() +func import_patterns(priority_ordered_search_path: Array) -> void: + for path in priority_ordered_search_path: + var pattern_list := [] + var dir := Directory.new() + dir.open(path) + dir.list_dir_begin() + var curr_file := dir.get_next() + while curr_file != "": + if curr_file.get_extension().to_lower() == "png": + pattern_list.append(curr_file) + curr_file = dir.get_next() + dir.list_dir_end() -func find_brushes(brushes_dir : Directory, path : String) -> Array: - var subdirectories := [] - var found_random_brush := 0 - path = Global.root_directory.plus_file(path) - brushes_dir.open(path) - brushes_dir.list_dir_begin(true) - var file := brushes_dir.get_next() - while file != "": - if file.get_extension().to_upper() == "PNG": + for pattern in pattern_list: var image := Image.new() - var err := image.load(path.plus_file(file)) + var err := image.load(path.plus_file(pattern)) if err == OK: - if "%" in file: - if found_random_brush == 0: - found_random_brush = Global.file_brush_container.get_child_count() - image.convert(Image.FORMAT_RGBA8) - Global.custom_brushes.append(image) - Global.create_brush_button(image, Global.Brush_Types.RANDOM_FILE, file.trim_suffix(".png")) - else: - var brush_button = Global.file_brush_container.get_child(found_random_brush) - brush_button.random_brushes.append(image) - else: - image.convert(Image.FORMAT_RGBA8) - Global.custom_brushes.append(image) - Global.create_brush_button(image, Global.Brush_Types.FILE, file.trim_suffix(".png")) - elif file.get_extension() == "": # Probably a directory - var subdir := "./%s" % [file] - if brushes_dir.dir_exists(subdir): # If it's an actual directory - subdirectories.append(subdir) + image.convert(Image.FORMAT_RGBA8) + Global.patterns.append(image) + + var pattern_button : BaseButton = load("res://Prefabs/PatternButton.tscn").instance() + pattern_button.image = image + var pattern_tex := ImageTexture.new() + pattern_tex.create_from_image(image, 0) + pattern_button.get_child(0).texture = pattern_tex + pattern_button.hint_tooltip = pattern + pattern_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND + Global.patterns_popup.get_node("ScrollContainer/PatternContainer").add_child(pattern_button) + + Global.pattern_left_image = Global.patterns[0] + var pattern_left_tex := ImageTexture.new() + pattern_left_tex.create_from_image(Global.pattern_left_image, 0) + Global.left_fill_pattern_container.get_child(0).get_child(0).texture = pattern_left_tex + + Global.pattern_right_image = Global.patterns[0] + var pattern_right_tex := ImageTexture.new() + pattern_right_tex.create_from_image(Global.pattern_right_image, 0) + Global.right_fill_pattern_container.get_child(0).get_child(0).texture = pattern_right_tex - file = brushes_dir.get_next() - brushes_dir.list_dir_end() - return subdirectories func import_gpl(path : String) -> Palette: var result : Palette = null diff --git a/Scripts/Main.gd b/Scripts/Main.gd index 3fa654dc8..5fbcdba61 100644 --- a/Scripts/Main.gd +++ b/Scripts/Main.gd @@ -172,6 +172,7 @@ func _ready() -> void: Global.layers_container.get_child(0).line_edit.text = Global.layers[0][0] Import.import_brushes(Global.directory_module.get_brushes_search_path_in_order()) + Import.import_patterns(Global.directory_module.get_patterns_search_path_in_order()) Global.left_color_picker.get_picker().presets_visible = false Global.right_color_picker.get_picker().presets_visible = false @@ -502,12 +503,8 @@ func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_le Global.left_brush_size_slider.visible = true Global.left_mirror_container.visible = true elif current_action == "Bucket": - Global.left_brush_type_container.visible = true - Global.left_brush_size_slider.visible = true Global.left_fill_area_container.visible = true Global.left_mirror_container.visible = true - if Global.current_left_brush_type == Global.Brush_Types.FILE or Global.current_left_brush_type == Global.Brush_Types.CUSTOM or Global.current_left_brush_type == Global.Brush_Types.RANDOM_FILE: - Global.left_color_interpolation_container.visible = true elif current_action == "LightenDarken": Global.left_brush_type_container.visible = true Global.left_brush_size_slider.visible = true @@ -538,12 +535,8 @@ func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_le Global.right_brush_size_slider.visible = true Global.right_mirror_container.visible = true elif current_action == "Bucket": - Global.right_brush_type_container.visible = true - Global.right_brush_size_slider.visible = true Global.right_fill_area_container.visible = true Global.right_mirror_container.visible = true - if Global.current_right_brush_type == Global.Brush_Types.FILE or Global.current_right_brush_type == Global.Brush_Types.CUSTOM or Global.current_right_brush_type == Global.Brush_Types.RANDOM_FILE: - Global.right_color_interpolation_container.visible = true elif current_action == "LightenDarken": Global.right_brush_type_container.visible = true Global.right_brush_size_slider.visible = true @@ -651,10 +644,36 @@ func _on_LeftFillAreaOptions_item_selected(ID : int) -> void: Global.left_fill_area = ID +func _on_LeftFillWithOptions_item_selected(ID : int) -> void: + Global.left_fill_with = ID + if ID == 1: + Global.left_fill_pattern_container.visible = true + else: + Global.left_fill_pattern_container.visible = false + + +func _on_LeftPatternTypeButton_pressed() -> void: + Global.pattern_window_position = "left" + Global.patterns_popup.popup(Rect2(Global.left_brush_type_button.rect_global_position, Vector2(226, 72))) + + func _on_RightFillAreaOptions_item_selected(ID : int) -> void: Global.right_fill_area = ID +func _on_RightFillWithOptions_item_selected(ID : int) -> void: + Global.right_fill_with = ID + if ID == 1: + Global.right_fill_pattern_container.visible = true + else: + Global.right_fill_pattern_container.visible = false + + +func _on_RightPatternTypeButton_pressed() -> void: + Global.pattern_window_position = "right" + Global.patterns_popup.popup(Rect2(Global.right_brush_type_button.rect_global_position, Vector2(226, 72))) + + func _on_LeftLightenDarken_item_selected(ID : int) -> void: Global.left_ld = ID diff --git a/Scripts/Palette/PaletteContainer.gd b/Scripts/Palette/PaletteContainer.gd index 44b264fa7..03166f118 100644 --- a/Scripts/Palette/PaletteContainer.gd +++ b/Scripts/Palette/PaletteContainer.gd @@ -2,11 +2,10 @@ extends GridContainer const palette_button = preload("res://Prefabs/PaletteButton.tscn") - -var palettes_path := "Palettes" var current_palette = "Default" var from_palette : Palette + func _ready() -> void: _load_palettes() diff --git a/Scripts/XDGDataPaths.gd b/Scripts/XDGDataPaths.gd index fe2b5026d..2fa8da356 100644 --- a/Scripts/XDGDataPaths.gd +++ b/Scripts/XDGDataPaths.gd @@ -16,6 +16,7 @@ const config_subdir_name := "pixelorama" const palettes_data_subdirectory := "Palettes" const brushes_data_subdirectory := "Brushes" +const patterns_data_subdirectory := "Patterns" # Get if we should use XDG standard or not nyaaaa @@ -69,7 +70,6 @@ func _init(): xdg_data_dirs = [] - func append_file_to_all(basepaths: Array, subpath: String) -> Array: var res := [] for _path in basepaths: @@ -81,27 +81,44 @@ func append_file_to_all(basepaths: Array, subpath: String) -> Array: func get_search_paths_in_order() -> Array: return [xdg_data_home] + xdg_data_dirs + # Gets the paths, in order of search priority, for palettes. func get_palette_search_path_in_order() -> Array: var base_paths := get_search_paths_in_order() return append_file_to_all(base_paths, palettes_data_subdirectory) + # Gets the paths, in order of search priority, for brushes. func get_brushes_search_path_in_order() -> Array: var base_paths := get_search_paths_in_order() return append_file_to_all(base_paths, brushes_data_subdirectory) +# Gets the paths, in order of search priority, for patterns. +func get_patterns_search_path_in_order() -> Array: + var base_paths := get_search_paths_in_order() + return append_file_to_all(base_paths, patterns_data_subdirectory) + + # Get the path that we are ok to be writing palettes to: func get_palette_write_path() -> String: return xdg_data_home.plus_file(palettes_data_subdirectory) + # Get the path that we are ok to be writing brushes to: func get_brushes_write_path() -> String: return xdg_data_home.plus_file(brushes_data_subdirectory) +# Get the path that we are ok to be writing patterns to: +func get_patterns_write_path() -> String: + return xdg_data_home.plus_file(patterns_data_subdirectory) + + # Ensure the user xdg directories exist: func ensure_xdg_user_dirs_exist() -> void: + if !OS.has_feature("standalone"): # Don't execute if we're in the editor + return + var base_dir := Directory.new() base_dir.open(raw_xdg_data_home) # Ensure the main config directory exists. @@ -112,6 +129,7 @@ func ensure_xdg_user_dirs_exist() -> void: actual_data_dir.open(xdg_data_home) var palette_writing_dir := get_palette_write_path() var brushes_writing_dir := get_brushes_write_path() + var pattern_writing_dir := get_patterns_write_path() # Create the palette and brush dirs if not actual_data_dir.dir_exists(palette_writing_dir): print("Making directory %s" % [palette_writing_dir]) @@ -119,3 +137,6 @@ func ensure_xdg_user_dirs_exist() -> void: if not actual_data_dir.dir_exists(brushes_writing_dir): print("Making directory %s" % [brushes_writing_dir]) actual_data_dir.make_dir(brushes_writing_dir) + if not actual_data_dir.dir_exists(pattern_writing_dir): + print("Making directory %s" % [pattern_writing_dir]) + actual_data_dir.make_dir(pattern_writing_dir) diff --git a/pixelorama/Patterns/.gdignore b/pixelorama/Patterns/.gdignore new file mode 100644 index 000000000..e69de29bb diff --git a/pixelorama/Patterns/Brick.png b/pixelorama/Patterns/Brick.png new file mode 100644 index 000000000..d16085a1c Binary files /dev/null and b/pixelorama/Patterns/Brick.png differ diff --git a/pixelorama/Patterns/Gravel.png b/pixelorama/Patterns/Gravel.png new file mode 100644 index 000000000..a5d2e668d Binary files /dev/null and b/pixelorama/Patterns/Gravel.png differ diff --git a/pixelorama/Patterns/Ground_leaves.png b/pixelorama/Patterns/Ground_leaves.png new file mode 100644 index 000000000..5a2869758 Binary files /dev/null and b/pixelorama/Patterns/Ground_leaves.png differ diff --git a/pixelorama/Patterns/Light_Blue_Texture.png b/pixelorama/Patterns/Light_Blue_Texture.png new file mode 100644 index 000000000..abe9ce725 Binary files /dev/null and b/pixelorama/Patterns/Light_Blue_Texture.png differ diff --git a/pixelorama/Patterns/Metro_tile.png b/pixelorama/Patterns/Metro_tile.png new file mode 100644 index 000000000..b44bf5bc0 Binary files /dev/null and b/pixelorama/Patterns/Metro_tile.png differ diff --git a/pixelorama/Patterns/Purple_Texture.png b/pixelorama/Patterns/Purple_Texture.png new file mode 100644 index 000000000..5a2869758 Binary files /dev/null and b/pixelorama/Patterns/Purple_Texture.png differ diff --git a/pixelorama/Patterns/White_Marble.png b/pixelorama/Patterns/White_Marble.png new file mode 100644 index 000000000..2ec5b6c17 Binary files /dev/null and b/pixelorama/Patterns/White_Marble.png differ diff --git a/pixelorama/Patterns/Wooden_planks_1.png b/pixelorama/Patterns/Wooden_planks_1.png new file mode 100644 index 000000000..a15a664ca Binary files /dev/null and b/pixelorama/Patterns/Wooden_planks_1.png differ diff --git a/pixelorama/Patterns/Yellow_Marble.png b/pixelorama/Patterns/Yellow_Marble.png new file mode 100644 index 000000000..b44bf5bc0 Binary files /dev/null and b/pixelorama/Patterns/Yellow_Marble.png differ diff --git a/pixelorama/Patterns/small_stonebricks.png b/pixelorama/Patterns/small_stonebricks.png new file mode 100644 index 000000000..38dc8326d Binary files /dev/null and b/pixelorama/Patterns/small_stonebricks.png differ diff --git a/pixelorama/Patterns/wooden_planks_2.png b/pixelorama/Patterns/wooden_planks_2.png new file mode 100644 index 000000000..58f80dcf4 Binary files /dev/null and b/pixelorama/Patterns/wooden_planks_2.png differ