diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e0c4287e..3fa423be4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased This update has been brought to you by the contributions of: -Laurenz Reinthaler (Schweini07), kleonc, Variable-ind +Laurenz Reinthaler (Schweini07), kleonc, Fayez Akhtar (Variable) ### Added - A new pan tool, used to move around the canvas. ([#399](https://github.com/Orama-Interactive/Pixelorama/pull/399)) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index d048255c4..1616d9e0c 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -358,7 +358,7 @@ func open_image_as_new_tab(path : String, image : Image) -> void: set_new_tab(project, path) -func open_image_as_spritesheet(path : String, image : Image, horizontal : int, vertical : int) -> void: +func open_image_as_spritesheet_tab(path : String, image : Image, horizontal : int, vertical : int) -> void: var project = Project.new([], path.get_file()) project.layers.append(Layer.new()) Global.projects.append(project) @@ -388,6 +388,69 @@ func open_image_as_spritesheet(path : String, image : Image, horizontal : int, v set_new_tab(project, path) +func open_image_as_spritesheet_layer(path : String, image : Image, file_name : String, horizontal : int, vertical : int, start_frame : int) -> void: + # data needed to slice images + horizontal = min(horizontal, image.get_size().x) + vertical = min(vertical, image.get_size().y) + var frame_width := image.get_size().x / horizontal + var frame_height := image.get_size().y / vertical + + # resize canvas to if "frame_width" or "frame_height" is too large + var project_width :int = max(frame_width, Global.current_project.size.x) + var project_height :int = max(frame_height, Global.current_project.size.y) + DrawingAlgos.resize_canvas(project_width, project_height,0 ,0) + + # slice images + var image_no :int = 0 + for yy in range(vertical): + for xx in range(horizontal): + var cropped_image := Image.new() + cropped_image = image.get_rect(Rect2(frame_width * xx, frame_height * yy, frame_width, frame_height)) + if (start_frame + (image_no)) < Global.current_project.frames.size(): + # if frames are already present then fill those first + if image_no == 0: + open_image_as_new_layer(cropped_image, file_name, start_frame + image_no) + else: + open_image_at_frame(cropped_image, Global.current_project.layers.size() - 1, start_frame + image_no) + else: + # if no more frames are present then start making new frames + open_image_as_new_frame(cropped_image, Global.current_project.layers.size() - 1) + image_no += 1 + + +func open_image_at_frame(image : Image, layer_index := 0, frame_index := 0) -> void: + var project = Global.current_project + image.crop(project.size.x, project.size.y) + + project.undos += 1 + project.undo_redo.create_action("Replaced Frame") + + var frames :Array = [] + # create a duplicate of "project.frames" + for i in project.frames.size(): + var frame := Frame.new() + frame.cels = project.frames[i].cels.duplicate(true) + frames.append(frame) + + for i in project.frames.size(): + if i == frame_index: + image.convert(Image.FORMAT_RGBA8) + image.lock() + frames[i].cels[layer_index] = (Cel.new(image, 1)) + project.undo_redo.add_do_property(project.frames[i], "cels", frames[i].cels) + project.undo_redo.add_undo_property(project.frames[i], "cels", project.frames[i].cels) + + project.undo_redo.add_do_property(project, "frames", frames) + project.undo_redo.add_do_property(project, "current_frame", frame_index) + + project.undo_redo.add_undo_property(project, "frames", project.frames) + project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) + + project.undo_redo.add_do_method(Global, "redo") + project.undo_redo.add_undo_method(Global, "undo") + project.undo_redo.commit_action() + + func open_image_as_new_frame(image : Image, layer_index := 0) -> void: var project = Global.current_project image.crop(project.size.x, project.size.y) @@ -445,6 +508,7 @@ func open_image_as_new_layer(image : Image, file_name : String, frame_index := 0 project.undo_redo.add_do_property(project.frames[i], "cels", new_cels) project.undo_redo.add_undo_property(project.frames[i], "cels", project.frames[i].cels) + new_layers.append(layer) project.undo_redo.add_do_property(project, "current_layer", new_layers.size() - 1) diff --git a/src/UI/Dialogs/AboutDialog.gd b/src/UI/Dialogs/AboutDialog.gd index cebb3cfa9..5799fe6e4 100644 --- a/src/UI/Dialogs/AboutDialog.gd +++ b/src/UI/Dialogs/AboutDialog.gd @@ -140,7 +140,7 @@ func create_contributors() -> void: contributors.create_item(contributor_root).set_text(0, " Vriska Weaver (henlo-birb)") contributors.create_item(contributor_root).set_text(0, " Rémi Verschelde (akien-mga)") contributors.create_item(contributor_root).set_text(0, " gschwind") - contributors.create_item(contributor_root).set_text(0, " Variable-ind") + contributors.create_item(contributor_root).set_text(0, " Fayez Akhtar (Variable)") func create_translators() -> void: diff --git a/src/UI/Dialogs/PreviewDialog.gd b/src/UI/Dialogs/PreviewDialog.gd index dad963b48..926c2c7d0 100644 --- a/src/UI/Dialogs/PreviewDialog.gd +++ b/src/UI/Dialogs/PreviewDialog.gd @@ -1,7 +1,7 @@ extends ConfirmationDialog -enum ImageImportOptions {NEW_TAB, SPRITESHEET, NEW_FRAME, NEW_LAYER, PALETTE, BRUSH, PATTERN} +enum ImageImportOptions {NEW_TAB, SPRITESHEET_TAB, SPRITESHEET_LAYER, NEW_FRAME, REPLACE_FRAME, NEW_LAYER, PALETTE, BRUSH, PATTERN} enum BrushTypes {FILE, PROJECT, RANDOM} var path : String @@ -14,19 +14,34 @@ var brush_type : int = BrushTypes.FILE onready var texture_rect : TextureRect = $VBoxContainer/CenterContainer/TextureRect onready var image_size_label : Label = $VBoxContainer/SizeContainer/ImageSizeLabel onready var frame_size_label : Label = $VBoxContainer/SizeContainer/FrameSizeLabel -onready var spritesheet_options = $VBoxContainer/HBoxContainer/SpritesheetOptions +onready var spritesheet_tab_options = $VBoxContainer/HBoxContainer/SpritesheetTabOptions +onready var spritesheet_layer_options = $VBoxContainer/HBoxContainer/SpritesheetLayerOptions onready var new_frame_options = $VBoxContainer/HBoxContainer/NewFrameOptions +onready var replace_frame_options = $VBoxContainer/HBoxContainer/ReplaceFrameOptions onready var new_layer_options = $VBoxContainer/HBoxContainer/NewLayerOptions onready var new_brush_options = $VBoxContainer/HBoxContainer/NewBrushOptions onready var new_brush_name = $VBoxContainer/HBoxContainer/NewBrushOptions/BrushName func _on_PreviewDialog_about_to_show() -> void: + var import_options :OptionButton= get_node("VBoxContainer/HBoxContainer/ImportOption") + + # # order as in ImageImportOptions enum + import_options.add_item("New tab") + import_options.add_item("Spritesheet (new tab)") + import_options.add_item("Spritesheet (new layer)") + import_options.add_item("New frame") + import_options.add_item("Replace Frame") + import_options.add_item("New layer") + import_options.add_item("New palette") + import_options.add_item("New brush") + import_options.add_item("New pattern") + var img_texture := ImageTexture.new() img_texture.create_from_image(image, 0) texture_rect.texture = img_texture - spritesheet_options.get_node("HorizontalFrames").max_value = min(spritesheet_options.get_node("HorizontalFrames").max_value, image.get_size().x) - spritesheet_options.get_node("VerticalFrames").max_value = min(spritesheet_options.get_node("VerticalFrames").max_value, image.get_size().y) + spritesheet_tab_options.get_node("HorizontalFrames").max_value = min(spritesheet_tab_options.get_node("HorizontalFrames").max_value, image.get_size().x) + spritesheet_tab_options.get_node("VerticalFrames").max_value = min(spritesheet_tab_options.get_node("VerticalFrames").max_value, image.get_size().y) image_size_label.text = tr("Image Size") + ": " + str(image.get_size().x) + "×" + str(image.get_size().y) frame_size_label.text = tr("Frame Size") + ": " + str(image.get_size().x) + "×" + str(image.get_size().y) @@ -44,13 +59,22 @@ func _on_PreviewDialog_confirmed() -> void: if current_import_option == ImageImportOptions.NEW_TAB: OpenSave.open_image_as_new_tab(path, image) - elif current_import_option == ImageImportOptions.SPRITESHEET: - OpenSave.open_image_as_spritesheet(path, image, spritesheet_horizontal, spritesheet_vertical) + elif current_import_option == ImageImportOptions.SPRITESHEET_TAB: + OpenSave.open_image_as_spritesheet_tab(path, image, spritesheet_horizontal, spritesheet_vertical) + + elif current_import_option == ImageImportOptions.SPRITESHEET_LAYER: + var frame_index : int = spritesheet_layer_options.get_node("AtFrameSpinbox").value - 1 + OpenSave.open_image_as_spritesheet_layer(path, image, path.get_basename().get_file(), spritesheet_horizontal, spritesheet_vertical, frame_index) elif current_import_option == ImageImportOptions.NEW_FRAME: var layer_index : int = new_frame_options.get_node("AtLayerSpinbox").value OpenSave.open_image_as_new_frame(image, layer_index) + elif current_import_option == ImageImportOptions.REPLACE_FRAME: + var layer_index : int = replace_frame_options.get_node("AtLayerSpinbox").value + var frame_index : int = replace_frame_options.get_node("AtFrameSpinbox").value - 1 + OpenSave.open_image_at_frame(image, layer_index, frame_index) + elif current_import_option == ImageImportOptions.NEW_LAYER: var frame_index : int = new_layer_options.get_node("AtFrameSpinbox").value - 1 OpenSave.open_image_as_new_layer(image, path.get_basename().get_file(), frame_index) @@ -77,23 +101,41 @@ func _on_PreviewDialog_confirmed() -> void: func _on_ImportOption_item_selected(id : int) -> void: current_import_option = id frame_size_label.visible = false - spritesheet_options.visible = false + spritesheet_tab_options.visible = false + spritesheet_layer_options.visible = false new_frame_options.visible = false + replace_frame_options.visible = false new_layer_options.visible = false new_brush_options.visible = false texture_rect.get_child(0).visible = false texture_rect.get_child(1).visible = false + rect_size.x = 550 - if id == ImageImportOptions.SPRITESHEET: + if id == ImageImportOptions.SPRITESHEET_TAB: frame_size_label.visible = true - spritesheet_options.visible = true + spritesheet_tab_options.visible = true texture_rect.get_child(0).visible = true texture_rect.get_child(1).visible = true + rect_size.x = spritesheet_tab_options.rect_size.x + + elif id == ImageImportOptions.SPRITESHEET_LAYER: + frame_size_label.visible = true + spritesheet_tab_options.visible = true + spritesheet_layer_options.visible = true + spritesheet_layer_options.get_node("AtFrameSpinbox").max_value = Global.current_project.frames.size() + texture_rect.get_child(0).visible = true + texture_rect.get_child(1).visible = true + rect_size.x = spritesheet_layer_options.rect_size.x elif id == ImageImportOptions.NEW_FRAME: new_frame_options.visible = true new_frame_options.get_node("AtLayerSpinbox").max_value = Global.current_project.layers.size() - 1 + elif id == ImageImportOptions.REPLACE_FRAME: + replace_frame_options.visible = true + replace_frame_options.get_node("AtLayerSpinbox").max_value = Global.current_project.layers.size() - 1 + replace_frame_options.get_node("AtFrameSpinbox").max_value = Global.current_project.frames.size() + elif id == ImageImportOptions.NEW_LAYER: new_layer_options.visible = true new_layer_options.get_node("AtFrameSpinbox").max_value = Global.current_project.frames.size() diff --git a/src/UI/Dialogs/PreviewDialog.tscn b/src/UI/Dialogs/PreviewDialog.tscn index e90821664..47ac7c8dc 100644 --- a/src/UI/Dialogs/PreviewDialog.tscn +++ b/src/UI/Dialogs/PreviewDialog.tscn @@ -82,22 +82,20 @@ margin_right = 151.0 margin_bottom = 20.0 mouse_default_cursor_shape = 2 text = "New tab" -items = [ "New tab", null, false, 0, null, "Spritesheet (new tab)", null, false, 1, null, "New frame", null, false, 2, null, "New layer", null, false, 3, null, "New palette", null, false, 4, null, "New brush", null, false, 5, null, "New pattern", null, false, 6, null ] -selected = 0 -[node name="SpritesheetOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] +[node name="SpritesheetTabOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] visible = false margin_left = 155.0 margin_right = 533.0 margin_bottom = 24.0 -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/SpritesheetOptions"] +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions"] margin_top = 5.0 margin_right = 118.0 margin_bottom = 19.0 text = "Horizontal frames:" -[node name="HorizontalFrames" type="SpinBox" parent="VBoxContainer/HBoxContainer/SpritesheetOptions"] +[node name="HorizontalFrames" type="SpinBox" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions"] margin_left = 122.0 margin_right = 196.0 margin_bottom = 24.0 @@ -105,14 +103,14 @@ mouse_default_cursor_shape = 2 min_value = 1.0 value = 1.0 -[node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/SpritesheetOptions"] +[node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions"] margin_left = 200.0 margin_top = 5.0 margin_right = 300.0 margin_bottom = 19.0 text = "Vertical frames:" -[node name="VerticalFrames" type="SpinBox" parent="VBoxContainer/HBoxContainer/SpritesheetOptions"] +[node name="VerticalFrames" type="SpinBox" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions"] margin_left = 304.0 margin_right = 378.0 margin_bottom = 24.0 @@ -120,6 +118,26 @@ mouse_default_cursor_shape = 2 min_value = 1.0 value = 1.0 +[node name="SpritesheetLayerOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] +visible = false +margin_left = 155.0 +margin_right = 692.0 +margin_bottom = 24.0 + +[node name="Label3" type="Label" parent="VBoxContainer/HBoxContainer/SpritesheetLayerOptions"] +margin_left = 382.0 +margin_top = 5.0 +margin_right = 459.0 +margin_bottom = 19.0 +text = "Start Frame:" + +[node name="AtFrameSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/SpritesheetLayerOptions"] +margin_left = 463.0 +margin_right = 537.0 +margin_bottom = 24.0 +min_value = 1.0 +value = 1.0 + [node name="NewFrameOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] visible = false margin_left = 155.0 @@ -139,6 +157,41 @@ margin_bottom = 24.0 mouse_default_cursor_shape = 2 max_value = 0.0 +[node name="ReplaceFrameOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] +visible = false +margin_left = 155.0 +margin_right = 433.0 +margin_bottom = 24.0 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceFrameOptions"] +margin_top = 5.0 +margin_right = 56.0 +margin_bottom = 19.0 +text = "At Layer:" + +[node name="AtLayerSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/ReplaceFrameOptions"] +margin_left = 60.0 +margin_right = 134.0 +margin_bottom = 24.0 +mouse_default_cursor_shape = 2 +max_value = 0.0 + +[node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceFrameOptions"] +margin_left = 138.0 +margin_top = 5.0 +margin_right = 200.0 +margin_bottom = 19.0 +text = "At Frame:" + +[node name="AtFrameSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/ReplaceFrameOptions"] +margin_left = 204.0 +margin_right = 278.0 +margin_bottom = 24.0 +mouse_default_cursor_shape = 2 +min_value = 1.0 +max_value = 0.0 +value = 1.0 + [node name="NewLayerOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] visible = false margin_left = 155.0 @@ -201,6 +254,6 @@ margin_bottom = 24.0 [connection signal="confirmed" from="." to="." method="_on_PreviewDialog_confirmed"] [connection signal="popup_hide" from="." to="." method="_on_PreviewDialog_popup_hide"] [connection signal="item_selected" from="VBoxContainer/HBoxContainer/ImportOption" to="." method="_on_ImportOption_item_selected"] -[connection signal="value_changed" from="VBoxContainer/HBoxContainer/SpritesheetOptions/HorizontalFrames" to="." method="_on_HorizontalFrames_value_changed"] -[connection signal="value_changed" from="VBoxContainer/HBoxContainer/SpritesheetOptions/VerticalFrames" to="." method="_on_VerticalFrames_value_changed"] +[connection signal="value_changed" from="VBoxContainer/HBoxContainer/SpritesheetTabOptions/HorizontalFrames" to="." method="_on_HorizontalFrames_value_changed"] +[connection signal="value_changed" from="VBoxContainer/HBoxContainer/SpritesheetTabOptions/VerticalFrames" to="." method="_on_VerticalFrames_value_changed"] [connection signal="item_selected" from="VBoxContainer/HBoxContainer/NewBrushOptions/BrushTypeOption" to="." method="_on_BrushTypeOption_item_selected"]