diff --git a/Main.tscn b/Main.tscn index e5f17182e..3dfe20ea0 100644 --- a/Main.tscn +++ b/Main.tscn @@ -16,13 +16,13 @@ anchor_bottom = 1.0 script = ExtResource( 1 ) [node name="UI" type="HBoxContainer" parent="."] +editor/display_folded = true anchor_right = 1.0 anchor_bottom = 1.0 size_flags_horizontal = 3 custom_constants/separation = 0 [node name="ToolPanel" type="Panel" parent="UI"] -editor/display_folded = true margin_right = 230.0 margin_bottom = 600.0 rect_min_size = Vector2( 230, 0 ) @@ -35,13 +35,13 @@ size_flags_horizontal = 3 size_flags_vertical = 3 [node name="MenusAndTools" type="VBoxContainer" parent="UI/ToolPanel/Tools"] -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 266.0 size_flags_vertical = 3 [node name="MenuItems" type="HBoxContainer" parent="UI/ToolPanel/Tools/MenusAndTools"] editor/display_folded = true -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 20.0 [node name="FileMenu" type="MenuButton" parent="UI/ToolPanel/Tools/MenusAndTools/MenuItems"] @@ -72,13 +72,11 @@ mouse_default_cursor_shape = 2 text = "Help" [node name="PaintToolsContainer" type="HBoxContainer" parent="UI/ToolPanel/Tools/MenusAndTools"] -editor/display_folded = true margin_top = 24.0 -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 44.0 [node name="Pencil" type="Button" parent="UI/ToolPanel/Tools/MenusAndTools/PaintToolsContainer"] -editor/display_folded = true margin_right = 51.0 margin_bottom = 20.0 hint_tooltip = "P for left mouse button @@ -94,7 +92,6 @@ centered = false offset = Vector2( 0, -10 ) [node name="Eraser" type="Button" parent="UI/ToolPanel/Tools/MenusAndTools/PaintToolsContainer"] -editor/display_folded = true margin_left = 55.0 margin_right = 106.0 margin_bottom = 20.0 @@ -121,9 +118,8 @@ button_mask = 3 text = "Bucket" [node name="ColorToolsContainer" type="HBoxContainer" parent="UI/ToolPanel/Tools/MenusAndTools"] -editor/display_folded = true margin_top = 48.0 -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 68.0 [node name="PaintAllPixelsSameColor" type="Button" parent="UI/ToolPanel/Tools/MenusAndTools/ColorToolsContainer"] @@ -148,9 +144,8 @@ button_mask = 3 text = "Lighten/Darken" [node name="SelectionToolsContainer2" type="HBoxContainer" parent="UI/ToolPanel/Tools/MenusAndTools"] -editor/display_folded = true margin_top = 72.0 -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 92.0 [node name="RectSelect" type="Button" parent="UI/ToolPanel/Tools/MenusAndTools/SelectionToolsContainer2"] @@ -165,30 +160,29 @@ text = "RectSelect" [node name="HSeparator" type="HSeparator" parent="UI/ToolPanel/Tools"] margin_top = 270.0 -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 274.0 [node name="ToolOptions" type="HBoxContainer" parent="UI/ToolPanel/Tools"] -editor/display_folded = true margin_top = 278.0 -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 544.0 size_flags_vertical = 3 custom_constants/separation = 0 [node name="LeftToolOptions" type="VBoxContainer" parent="UI/ToolPanel/Tools/ToolOptions"] -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 266.0 size_flags_horizontal = 3 [node name="LeftLabel" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions"] -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 14.0 text = "Left tool options" [node name="LeftIndicatorCheckbox" type="CheckBox" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions"] margin_top = 18.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 42.0 hint_tooltip = "Show left mouse indicator when drawing" mouse_default_cursor_shape = 2 @@ -207,13 +201,13 @@ size_flags_vertical = 0 [node name="BrushSizeLabel" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions"] margin_top = 82.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 96.0 text = "Brush size: " [node name="LeftBrushSizeEdit" type="SpinBox" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions"] margin_top = 100.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 124.0 mouse_default_cursor_shape = 2 min_value = 1.0 @@ -222,14 +216,14 @@ suffix = "px" [node name="ColorComesFrom" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions"] margin_top = 128.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 142.0 text = "Brush color from" [node name="InterpolateColor" type="HBoxContainer" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions"] editor/display_folded = true margin_top = 146.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 162.0 [node name="BrushColorLabel" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions/InterpolateColor"] @@ -241,7 +235,7 @@ text = "B" [node name="LeftInterpolateFactor" type="HSlider" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions/InterpolateColor"] margin_left = 13.0 -margin_right = 107.0 +margin_right = 101.0 margin_bottom = 16.0 hint_tooltip = "Choose if the brush's color should come from the brush itself (left), or the currently selected color (right)" size_flags_horizontal = 3 @@ -251,44 +245,44 @@ value = 0.5 ticks_on_borders = true [node name="SelectedColorLabel" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions/InterpolateColor"] -margin_left = 111.0 +margin_left = 105.0 margin_top = 1.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 15.0 rect_pivot_offset = Vector2( -90, -47 ) text = "C" [node name="LeftHorizontalMirroring" type="CheckBox" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions"] margin_top = 166.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 190.0 text = "Horiz. Mirror" [node name="LeftVerticalMirroring" type="CheckBox" parent="UI/ToolPanel/Tools/ToolOptions/LeftToolOptions"] margin_top = 194.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 218.0 text = "Vert. Mirror" [node name="VSeparator" type="VSeparator" parent="UI/ToolPanel/Tools/ToolOptions"] -margin_left = 119.0 -margin_right = 123.0 +margin_left = 113.0 +margin_right = 117.0 margin_bottom = 266.0 [node name="RightToolOptions" type="VBoxContainer" parent="UI/ToolPanel/Tools/ToolOptions"] -margin_left = 123.0 -margin_right = 242.0 +margin_left = 117.0 +margin_right = 230.0 margin_bottom = 266.0 size_flags_horizontal = 3 [node name="RightLabel" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions"] -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 14.0 text = "Right tool options" [node name="RightIndicatorCheckbox" type="CheckBox" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions"] margin_top = 18.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 42.0 hint_tooltip = "Show right mouse indicator when drawing" mouse_default_cursor_shape = 2 @@ -306,13 +300,13 @@ size_flags_vertical = 0 [node name="BrushSizeLabel" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions"] margin_top = 82.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 96.0 text = "Brush size: " [node name="RightBrushSizeEdit" type="SpinBox" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions"] margin_top = 100.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 124.0 mouse_default_cursor_shape = 2 min_value = 1.0 @@ -321,14 +315,14 @@ suffix = "px" [node name="ColorComesFrom" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions"] margin_top = 128.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 142.0 text = "Brush color from" [node name="InterpolateColor" type="HBoxContainer" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions"] editor/display_folded = true margin_top = 146.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 162.0 [node name="BrushColorLabel" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions/InterpolateColor"] @@ -340,7 +334,7 @@ text = "B" [node name="RightInterpolateFactor" type="HSlider" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions/InterpolateColor"] margin_left = 13.0 -margin_right = 107.0 +margin_right = 101.0 margin_bottom = 16.0 hint_tooltip = "Choose if the brush's color should come from the brush itself (left), or the currently selected color (right)" size_flags_horizontal = 3 @@ -350,34 +344,33 @@ value = 0.5 ticks_on_borders = true [node name="SelectedColorLabel" type="Label" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions/InterpolateColor"] -margin_left = 111.0 +margin_left = 105.0 margin_top = 1.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 15.0 rect_pivot_offset = Vector2( -90, -47 ) text = "C" [node name="RightHorizontalMirroring" type="CheckBox" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions"] margin_top = 166.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 190.0 text = "Horiz. Mirror" [node name="RightVerticalMirroring" type="CheckBox" parent="UI/ToolPanel/Tools/ToolOptions/RightToolOptions"] margin_top = 194.0 -margin_right = 119.0 +margin_right = 113.0 margin_bottom = 218.0 text = "Vert. Mirror" [node name="HSeparator2" type="HSeparator" parent="UI/ToolPanel/Tools"] margin_top = 548.0 -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 552.0 [node name="BrushesContainer" type="ScrollContainer" parent="UI/ToolPanel/Tools"] -editor/display_folded = true margin_top = 556.0 -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 592.0 size_flags_horizontal = 3 scroll_vertical_enabled = false @@ -402,7 +395,7 @@ offset = Vector2( 28, 0 ) [node name="HSeparator3" type="HSeparator" parent="UI/ToolPanel/Tools"] margin_top = 596.0 -margin_right = 242.0 +margin_right = 230.0 margin_bottom = 600.0 [node name="CanvasAndTimeline" type="VBoxContainer" parent="UI"] @@ -412,6 +405,7 @@ margin_bottom = 600.0 size_flags_horizontal = 3 [node name="HBoxContainer" type="HBoxContainer" parent="UI/CanvasAndTimeline"] +editor/display_folded = true margin_right = 634.0 margin_bottom = 464.0 size_flags_horizontal = 3 @@ -472,7 +466,6 @@ zoom = Vector2( 0.15, 0.15 ) script = ExtResource( 6 ) [node name="AnimationTimeline" type="Panel" parent="UI/CanvasAndTimeline"] -editor/display_folded = true margin_top = 468.0 margin_right = 634.0 margin_bottom = 600.0 @@ -868,8 +861,8 @@ resizable = true mode = 0 access = 2 filters = PoolStringArray( "*.pxo ; Pixelorama Project" ) -current_dir = "/home/danielnaoexiste/Documents/Prog/Pixelorama" -current_path = "/home/danielnaoexiste/Documents/Prog/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 @@ -883,8 +876,8 @@ margin_bottom = 48.0 resizable = true access = 2 filters = PoolStringArray( "*.pxo ; Pixelorama Project" ) -current_dir = "/home/danielnaoexiste/Documents/Prog/Pixelorama" -current_path = "/home/danielnaoexiste/Documents/Prog/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" type="FileDialog" parent="."] margin_right = 515.0 @@ -894,8 +887,8 @@ resizable = true mode = 1 access = 2 filters = PoolStringArray( "*jpg, *.png ; JPG, PNG Images" ) -current_dir = "/home/danielnaoexiste/Documents/Prog/Pixelorama" -current_path = "/home/danielnaoexiste/Documents/Prog/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="ExportSprites" type="FileDialog" parent="."] anchor_left = 0.5 @@ -910,8 +903,8 @@ window_title = "Export sprite" resizable = true access = 2 filters = PoolStringArray( "*.png ; PNG Image" ) -current_dir = "/home/danielnaoexiste/Documents/Prog/Pixelorama" -current_path = "/home/danielnaoexiste/Documents/Prog/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="ScaleImage" type="ConfirmationDialog" parent="."] editor/display_folded = true diff --git a/Scripts/BrushButton.gd b/Scripts/BrushButton.gd index d82bea53f..dc026daa9 100644 --- a/Scripts/BrushButton.gd +++ b/Scripts/BrushButton.gd @@ -11,7 +11,7 @@ func _on_BrushButton_pressed() -> void: if custom_brush_index > -1: Global.custom_left_brush_index = custom_brush_index Global.update_left_custom_brush() - + elif Input.is_action_just_released("right_mouse"): Global.current_right_brush_type = brush_type Global.right_brush_indicator.get_parent().remove_child(Global.right_brush_indicator) diff --git a/Scripts/Canvas.gd b/Scripts/Canvas.gd index 25e5c6ff2..11b544452 100644 --- a/Scripts/Canvas.gd +++ b/Scripts/Canvas.gd @@ -11,6 +11,7 @@ var frame_button : VBoxContainer var frame_texture_rect : TextureRect var previous_mouse_pos := Vector2.ZERO +var previous_action := "None" var mouse_inside_canvas := false #used for undo var sprite_changed_this_frame := false #for optimization purposes @@ -24,30 +25,30 @@ func _ready() -> void: #Background trans_background = ImageTexture.new() trans_background.create_from_image(load("res://Assets/Graphics/Transparent Background.png"), 0) - + #The sprite itself if layers.empty(): var sprite := Image.new() sprite.create(size.x, size.y, false, Image.FORMAT_RGBA8) - + sprite.lock() var tex := ImageTexture.new() tex.create_from_image(sprite, 0) - + #Store [Image, ImageTexture, Layer Name, Visibity boolean] layers.append([sprite, tex, "Layer 0", true]) - + generate_layer_panels() - + frame_button = load("res://Prefabs/FrameButton.tscn").instance() frame_button.name = "Frame_%s" % frame frame_button.get_node("FrameButton").frame = frame frame_button.get_node("FrameID").text = str(frame + 1) Global.frame_container.add_child(frame_button) - + frame_texture_rect = Global.find_node_by_name(frame_button, "FrameTexture") frame_texture_rect.texture = layers[0][1] #ImageTexture current_layer_index - + camera_zoom() func camera_zoom() -> void: @@ -82,7 +83,7 @@ func _process(delta) -> void: elif Input.is_mouse_button_pressed(BUTTON_RIGHT): current_mouse_button = "right_mouse" current_action = Global.current_right_tool - + if visible: if !point_in_rectangle(mouse_pos, location, location + size): if !Input.is_mouse_button_pressed(BUTTON_LEFT) && !Input.is_mouse_button_pressed(BUTTON_RIGHT): @@ -91,8 +92,22 @@ func _process(delta) -> void: Global.cursor_position_label.text = "[%sx%s]" % [size.x, size.y] else: Global.cursor_position_label.text = "[%sx%s] %s, %s" % [size.x, size.y, mouse_pos_floored.x, mouse_pos_floored.y] - #Handle current tool - match current_action: + + + #Handle Undo/Redo + if point_in_rectangle(mouse_pos, location, location + size) && Global.can_draw && Global.has_focus: + if Input.is_action_just_pressed("left_mouse") || Input.is_action_just_pressed("right_mouse"): + if current_action != "None": + if current_action == "RectSelect": + handle_undo("Rectangle Select") + else: + handle_undo("Draw") + + elif Input.is_action_just_released("left_mouse") || Input.is_action_just_released("right_mouse"): + if previous_action != "None" && previous_action != "RectSelect": + handle_redo("Draw") + + match current_action: #Handle current tool "Pencil": var current_color : Color if current_mouse_button == "left_mouse": @@ -117,7 +132,7 @@ func _process(delta) -> void: current_color = Global.right_color_picker.color horizontal_mirror = Global.right_horizontal_mirror vertical_mirror = Global.right_vertical_mirror - + flood_fill(mouse_pos, layers[current_layer_index][0].get_pixelv(mouse_pos), current_color) if horizontal_mirror: var pos := Vector2(mirror_x, mouse_pos.y) @@ -128,15 +143,15 @@ func _process(delta) -> void: if horizontal_mirror && vertical_mirror: var pos := Vector2(mirror_x, mirror_y) flood_fill(pos, layers[current_layer_index][0].get_pixelv(pos), current_color) - + "PaintAllPixelsSameColor": - if point_in_rectangle(mouse_pos, location, location + size) && Global.current_frame == frame: + if point_in_rectangle(mouse_pos, location, location + size) && Global.can_draw && Global.has_focus && Global.current_frame == frame: var current_color : Color if current_mouse_button == "left_mouse": current_color = Global.left_color_picker.color elif current_mouse_button == "right_mouse": current_color = Global.right_color_picker.color - + var pixel_color : Color = layers[current_layer_index][0].get_pixelv(mouse_pos) for xx in size.x: for yy in size.y: @@ -145,7 +160,7 @@ func _process(delta) -> void: layers[current_layer_index][0].set_pixel(xx, yy, current_color) sprite_changed_this_frame = true "LightenDarken": - if point_in_rectangle(mouse_pos, location, location + size): + if point_in_rectangle(mouse_pos, location, location + size) && Global.can_draw && Global.has_focus && Global.current_frame == frame: var pixel_color : Color = layers[current_layer_index][0].get_pixelv(mouse_pos) var amount := 0.05 var color_changed := pixel_color.lightened(amount) @@ -177,14 +192,14 @@ func _process(delta) -> void: Global.selection_rectangle.polygon[1] = Vector2(end_pos.x, start_pos.y) Global.selection_rectangle.polygon[2] = end_pos Global.selection_rectangle.polygon[3] = Vector2(start_pos.x, end_pos.y) - + if !is_making_line: previous_mouse_pos = mouse_pos previous_mouse_pos.x = clamp(previous_mouse_pos.x, location.x, location.x + size.x) previous_mouse_pos.y = clamp(previous_mouse_pos.y, location.y, location.y + size.y) else: line_2d.set_point_position(1, mouse_pos) - + if is_making_selection != "None": #If we're making a selection if Input.is_action_just_released(is_making_selection): #Finish selection when button is released var start_pos = Global.selection_rectangle.polygon[0] @@ -193,30 +208,54 @@ func _process(delta) -> void: var temp = end_pos.x end_pos.x = start_pos.x start_pos.x = temp - + if start_pos.y > end_pos.y: var temp = end_pos.y end_pos.y = start_pos.y start_pos.y = temp - + Global.selection_rectangle.polygon[0] = start_pos Global.selection_rectangle.polygon[1] = Vector2(end_pos.x, start_pos.y) Global.selection_rectangle.polygon[2] = end_pos Global.selection_rectangle.polygon[3] = Vector2(start_pos.x, end_pos.y) - + for xx in range(start_pos.x, end_pos.x): for yy in range(start_pos.y, end_pos.y): Global.selected_pixels.append(Vector2(xx, yy)) is_making_selection = "None" - + handle_redo("Rectangle Select") + + previous_action = current_action if sprite_changed_this_frame: update_texture(current_layer_index) - +func handle_undo(action : String) -> void: + #I'm not sure why I have to unlock it, but... + #...if I don't, it doesn't work properly + layers[current_layer_index][0].unlock() + var data = layers[current_layer_index][0].data + layers[current_layer_index][0].lock() + Global.undo_redo.create_action(action) + Global.undo_redo.add_undo_property(layers[current_layer_index][0], "data", data) + if action == "Rectangle Select": + var selected_pixels = Global.selected_pixels.duplicate() + Global.undo_redo.add_undo_property(Global.selection_rectangle, "polygon", Global.selection_rectangle.polygon) + Global.undo_redo.add_undo_property(Global, "selected_pixels", selected_pixels) + Global.undo_redo.add_undo_method(Global, "undo", self, current_layer_index) + +func handle_redo(action : String) -> void: + Global.undo_redo.add_do_property(layers[current_layer_index][0], "data", layers[current_layer_index][0].data) + if action == "Rectangle Select": + Global.undo_redo.add_do_property(Global.selection_rectangle, "polygon", Global.selection_rectangle.polygon) + Global.undo_redo.add_do_property(Global, "selected_pixels", Global.selected_pixels) + Global.undo_redo.add_do_method(Global, "redo", self, current_layer_index) + Global.undo_redo.commit_action() + print("Do: ", Global.undo_redo.get_current_action_name()) + func update_texture(layer_index : int) -> void: layers[layer_index][1].create_from_image(layers[layer_index][0], 0) get_layer_container(layer_index).get_child(0).get_child(1).texture = layers[layer_index][1] - + #This code is used to update the texture in the animation timeline frame button #but blend_rect causes major performance issues on large images var whole_image := Image.new() @@ -249,7 +288,7 @@ func _draw() -> void: for texture in Global.canvases[Global.current_frame - i].layers: color.a = 0.6/i draw_texture(texture[1], location, color) - + #Future if Global.onion_skinning_future_rate > 0: var color : Color @@ -262,12 +301,12 @@ func _draw() -> void: for texture in Global.canvases[Global.current_frame + i].layers: color.a = 0.6/i draw_texture(texture[1], location, color) - + #Draw current frame layers for texture in layers: if texture[3]: #if it's visible draw_texture(texture[1], location) - + if Global.tile_mode: draw_texture(texture[1], Vector2(location.x, location.y + size.y)) #Down draw_texture(texture[1], Vector2(location.x - size.x, location.y + size.y)) #Down Left @@ -277,14 +316,14 @@ func _draw() -> void: draw_texture(texture[1], Vector2(location.x + size.x, location.y - size.y)) #Up right draw_texture(texture[1], Vector2(location.x + size.x, location.y)) #Right draw_texture(texture[1], location + size) #Down right - + #Idea taken from flurick (on GitHub) if Global.draw_grid: for x in size.x: draw_line(Vector2(x, location.y), Vector2(x, size.y), Color.black, true) for y in size.y: draw_line(Vector2(location.x, y), Vector2(size.x, y), Color.black, true) - + #Draw rectangle to indicate the pixel currently being hovered on var mouse_pos := get_local_mouse_position() + location if point_in_rectangle(mouse_pos, location, location + size): @@ -299,7 +338,7 @@ func _draw() -> void: var custom_brush_size = Global.custom_left_brush_image.get_size() - Vector2.ONE var dst := rectangle_center(mouse_pos, custom_brush_size) draw_texture(Global.custom_left_brush_texture, dst) - + if Global.right_square_indicator_visible: match Global.current_right_brush_type: Global.BRUSH_TYPES.PIXEL: @@ -315,7 +354,7 @@ func generate_layer_panels() -> void: for child in Global.vbox_layer_container.get_children(): if child is PanelContainer: child.queue_free() - + current_layer_index = layers.size() - 1 if layers.size() == 1: Global.remove_layer_button.disabled = true @@ -323,7 +362,7 @@ func generate_layer_panels() -> void: else: Global.remove_layer_button.disabled = false Global.remove_layer_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND - + for i in range(layers.size() -1, -1, -1): var layer_container = load("res://Prefabs/LayerContainer.tscn").instance() layers[i][2] = "Layer %s" % i @@ -365,7 +404,7 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String) -> var brush_index := -1 var custom_brush_image : Image var horizontal_mirror := false - var vertical_mirror := false + var vertical_mirror := false if current_mouse_button == "left_mouse": brush_size = Global.left_brush_size brush_type = Global.current_left_brush_type @@ -380,7 +419,7 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String) -> custom_brush_image = Global.custom_right_brush_image horizontal_mirror = Global.right_horizontal_mirror vertical_mirror = Global.right_vertical_mirror - + var west_limit := location.x var east_limit := location.x + size.x var north_limit := location.y @@ -390,12 +429,12 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String) -> east_limit = min(east_limit, Global.selection_rectangle.polygon[2].x) north_limit = max(north_limit, Global.selection_rectangle.polygon[0].y) south_limit = min(south_limit, Global.selection_rectangle.polygon[2].y) - + var start_pos_x var start_pos_y var end_pos_x var end_pos_y - + match(brush_type): Global.BRUSH_TYPES.PIXEL: start_pos_x = pos.x - (brush_size >> 1) @@ -423,7 +462,7 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String) -> if layers[current_layer_index][0].get_pixel(mirror_x, mirror_y) != color: #don't draw the same pixel over and over layers[current_layer_index][0].set_pixel(mirror_x, mirror_y, color) sprite_changed_this_frame = true - + Global.BRUSH_TYPES.CUSTOM: var custom_brush_size := custom_brush_image.get_size() - Vector2.ONE pos = pos.floor() @@ -432,7 +471,7 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String) -> #Rectangle with the same size as the brush, but at cursor's position #var pos_rect_position := rectangle_center(pos, custom_brush_size) var pos_rect := Rect2(dst, custom_brush_size + Vector2.ONE) - + #The selection rectangle #If there's no rectangle, the whole canvas is considered a selection var selection_rect := Rect2() @@ -443,7 +482,7 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String) -> #If the size is 0, that means that the brush wasn't positioned inside the selection if pos_rect_clipped.size == Vector2.ZERO: return - + #Re-position src_rect and dst based on the clipped position var pos_difference := (pos_rect.position - pos_rect_clipped.position).abs() #Obviously, if pos_rect and pos_rect_clipped are the same, pos_difference is Vector2.ZERO @@ -454,11 +493,11 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String) -> #... make sure pixels aren't being drawn outside the selection by adjusting src_rect's size src_rect.size.x = min(src_rect.size.x, selection_rect.size.x) src_rect.size.y = min(src_rect.size.y, selection_rect.size.y) - + #Handle mirroring var mirror_x := east_limit + west_limit - dst.x - 1 var mirror_y := south_limit + north_limit - dst.y - 1 - + if color.a > 0: #If it's the pencil layers[current_layer_index][0].blend_rect(custom_brush_image, src_rect, dst) if horizontal_mirror: @@ -467,14 +506,14 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String) -> layers[current_layer_index][0].blend_rect(custom_brush_image, src_rect, Vector2(dst.x, mirror_y)) if horizontal_mirror && vertical_mirror: layers[current_layer_index][0].blend_rect(custom_brush_image, src_rect, Vector2(mirror_x, mirror_y)) - + else: #if it's transparent - if it's the eraser var custom_brush := Image.new() custom_brush.copy_from(Global.custom_brushes[brush_index]) custom_brush_size = custom_brush.get_size() custom_brush.resize(custom_brush_size.x * brush_size, custom_brush_size.y * brush_size, Image.INTERPOLATE_NEAREST) var custom_brush_blended = Global.blend_image_with_color(custom_brush, color, 1) - + layers[current_layer_index][0].blit_rect_mask(custom_brush_blended, custom_brush, src_rect, dst) if horizontal_mirror: layers[current_layer_index][0].blit_rect_mask(custom_brush_blended, custom_brush, src_rect, Vector2(mirror_x, dst.y)) @@ -482,7 +521,7 @@ func draw_pixel(pos : Vector2, color : Color, current_mouse_button : String) -> layers[current_layer_index][0].blit_rect_mask(custom_brush_blended, custom_brush, src_rect, Vector2(dst.x, mirror_y)) if horizontal_mirror && vertical_mirror: layers[current_layer_index][0].blit_rect_mask(custom_brush_blended, custom_brush, src_rect, Vector2(mirror_x, mirror_y)) - + layers[current_layer_index][0].lock() sprite_changed_this_frame = true @@ -529,10 +568,10 @@ func flood_fill(pos : Vector2, target_color : Color, replace_color : Color) -> v east_limit = min(east_limit, Global.selection_rectangle.polygon[2].x) north_limit = max(north_limit, Global.selection_rectangle.polygon[0].y) south_limit = min(south_limit, Global.selection_rectangle.polygon[2].y) - + if !point_in_rectangle(pos, Vector2(west_limit - 1, north_limit - 1), Vector2(east_limit, south_limit)): return - + var q = [pos] for n in q: var west : Vector2 = n @@ -566,4 +605,3 @@ func rectangle_center(pos : Vector2, size : Vector2) -> Vector2: func _on_Timer_timeout() -> void: Global.can_draw = true - \ No newline at end of file diff --git a/Scripts/Global.gd b/Scripts/Global.gd index ad0afdc87..c4314790e 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -1,5 +1,6 @@ extends Node +var undo_redo : UndoRedo var current_frame := 0 setget set_current_frame_label # warning-ignore:unused_class_variable var can_draw := false @@ -102,6 +103,7 @@ var custom_right_brush_texture := ImageTexture.new() func _ready() -> void: + undo_redo = UndoRedo.new() var root = get_tree().get_root() canvas = find_node_by_name(root, "Canvas") canvases.append(canvas) @@ -111,10 +113,10 @@ func _ready() -> void: split_screen_button = find_node_by_name(root, "SplitScreenButton") camera = find_node_by_name(canvas_parent, "Camera2D") camera2 = find_node_by_name(canvas_parent.get_parent().get_parent(), "Camera2D2") - + selection_rectangle = find_node_by_name(root, "SelectionRectangle") image_clipboard = Image.new() - + file_menu = find_node_by_name(root, "FileMenu") edit_menu = find_node_by_name(root, "EditMenu") view_menu = find_node_by_name(root, "ViewMenu") @@ -127,10 +129,10 @@ func _ready() -> void: right_brush_size_edit = find_node_by_name(root, "RightBrushSizeEdit") left_interpolate_slider = find_node_by_name(root, "LeftInterpolateFactor") right_interpolate_slider = find_node_by_name(root, "RightInterpolateFactor") - + left_brush_indicator = find_node_by_name(root, "LeftBrushIndicator") right_brush_indicator = find_node_by_name(root, "RightBrushIndicator") - + loop_animation_button = find_node_by_name(root, "LoopAnim") play_forward = find_node_by_name(root, "PlayForward") play_backwards = find_node_by_name(root, "PlayBackwards") @@ -147,18 +149,30 @@ func _ready() -> void: zoom_level_label = find_node_by_name(root, "ZoomLevel") current_frame_label = find_node_by_name(root, "CurrentFrame") -#Thanks to https://godotengine.org/qa/17524/how-to-find-an-instanced-scene-by-its-name +#Thanks to https://godotengine.org/qa/17524/how-to-find-an-instanced-scene-by-its-name func find_node_by_name(root, node_name) -> Node: - if root.get_name() == node_name: + if root.get_name() == node_name: return root for child in root.get_children(): if child.get_name() == node_name: return child var found = find_node_by_name(child, node_name) - if found: + if found: return found return null +func undo(canvas : Canvas, layer_index : int) -> void: + var action_name : String = undo_redo.get_current_action_name() + if action_name == "Draw" || action_name == "Rectangle Select": + canvas.update_texture(layer_index) + print("Undo: ", action_name) + +func redo(canvas : Canvas, layer_index : int) -> void: + var action_name : String = undo_redo.get_current_action_name() + if action_name == "Draw" || action_name == "Rectangle Select": + canvas.update_texture(layer_index) + print("Redo: ", action_name) + func change_frame() -> void: for c in canvases: c.visible = false @@ -174,7 +188,7 @@ func handle_layer_order_buttons() -> void: else: move_left_frame_button.disabled = false move_left_frame_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND - + if current_frame == canvases.size() - 1: move_right_frame_button.disabled = true move_right_frame_button.mouse_default_cursor_shape = Control.CURSOR_FORBIDDEN @@ -212,7 +226,7 @@ func update_left_custom_brush() -> void: custom_brush.resize(custom_brush_size.x * left_brush_size, custom_brush_size.y * left_brush_size, Image.INTERPOLATE_NEAREST) custom_left_brush_image = blend_image_with_color(custom_brush, left_color_picker.color, left_interpolate_slider.value) custom_left_brush_texture.create_from_image(custom_left_brush_image, 0) - + func update_right_custom_brush() -> void: if custom_right_brush_index > -1: var custom_brush := Image.new() diff --git a/Scripts/LayerContainer.gd b/Scripts/LayerContainer.gd index 175d1fa1a..88c81db65 100644 --- a/Scripts/LayerContainer.gd +++ b/Scripts/LayerContainer.gd @@ -26,14 +26,14 @@ func changed_selection() -> void: if Global.canvas.current_layer_index == child.i: child.currently_selected = true child.get_stylebox("panel").bg_color = Color("282532") - + if Global.canvas.current_layer_index < Global.canvas.layers.size() - 1: Global.move_up_layer_button.disabled = false Global.move_up_layer_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND else: Global.move_up_layer_button.disabled = true Global.move_up_layer_button.mouse_default_cursor_shape = Control.CURSOR_FORBIDDEN - + if Global.canvas.current_layer_index > 0: Global.move_down_layer_button.disabled = false Global.move_down_layer_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND diff --git a/Scripts/Main.gd b/Scripts/Main.gd index b49ea631c..6f9ba966b 100644 --- a/Scripts/Main.gd +++ b/Scripts/Main.gd @@ -19,7 +19,7 @@ func _ready() -> void: # Set a minimum window size to prevent UI elements from collapsing on each other. # This property is only available in 3.2alpha or later, so use `set()` to fail gracefully if it doesn't exist. OS.set("min_window_size", Vector2(1024, 600)) - + var file_menu_items := { "New..." : KEY_MASK_CTRL + KEY_N, "Open..." : KEY_MASK_CTRL + KEY_O, @@ -35,9 +35,9 @@ func _ready() -> void: "Crop Image" : 0, "Clear Selection" : 0, "Flip Horizontal": KEY_MASK_SHIFT + KEY_H, - "Flip Vertical": KEY_MASK_SHIFT + KEY_V - #"Undo" : KEY_MASK_CTRL + KEY_Z, - #"Redo" : KEY_MASK_SHIFT + KEY_MASK_CTRL + KEY_Z, + "Flip Vertical": KEY_MASK_SHIFT + KEY_V, + "Undo" : KEY_MASK_CTRL + KEY_Z, + "Redo" : KEY_MASK_SHIFT + KEY_MASK_CTRL + KEY_Z } var view_menu_items := { "Tile Mode" : KEY_MASK_CTRL + KEY_T, @@ -50,7 +50,7 @@ func _ready() -> void: var edit_menu : PopupMenu = Global.edit_menu.get_popup() view_menu = Global.view_menu.get_popup() var help_menu : PopupMenu = Global.help_menu.get_popup() - + var i = 0 for item in file_menu_items.keys(): file_menu.add_item(item, i, file_menu_items[item]) @@ -67,12 +67,12 @@ func _ready() -> void: for item in help_menu_items.keys(): help_menu.add_item(item, i, help_menu_items[item]) i += 1 - + file_menu.connect("id_pressed", self, "file_menu_id_pressed") edit_menu.connect("id_pressed", self, "edit_menu_id_pressed") view_menu.connect("id_pressed", self, "view_menu_id_pressed") help_menu.connect("id_pressed", self, "help_menu_id_pressed") - + var root = get_tree().get_root() #Node, left mouse shortcut, right mouse shortcut tools.append([Global.find_node_by_name(root, "Pencil"), "left_pencil_tool", "right_pencil_tool"]) @@ -81,15 +81,15 @@ func _ready() -> void: tools.append([Global.find_node_by_name(root, "PaintAllPixelsSameColor"), "left_paint_all_tool", "right_paint_all_tool"]) tools.append([Global.find_node_by_name(root, "LightenDarken"), "left_lightdark_tool", "right_lightdark_tool"]) tools.append([Global.find_node_by_name(root, "RectSelect"), "left_rectangle_select_tool", "right_rectangle_select_tool"]) - + for t in tools: t[0].connect("pressed", self, "_on_Tool_pressed", [t[0]]) - + #Options for Import import_as_new_frame = CheckBox.new() import_as_new_frame.text = "Import as new frame?" $ImportSprites.get_vbox().add_child(import_as_new_frame) - + #Options for Export export_all_frames = CheckBox.new() export_all_frames.text = "Export all frames?" @@ -100,7 +100,7 @@ func _ready() -> void: $ExportSprites.get_vbox().add_child(export_all_frames) $ExportSprites.get_vbox().add_child(export_as_single_file) $ExportSprites.get_vbox().add_child(export_vertical_spritesheet) - + func _input(event): for t in tools: #Handle tool shortcuts @@ -156,16 +156,16 @@ func edit_menu_id_pressed(id : int) -> void: while(i < Global.canvas.layers.size() - 1 && Global.canvas.layers[i][0].get_used_rect() == Rect2(0, 0, 0, 0)): i += 1 used_rect = Global.canvas.layers[i][0].get_used_rect() - + #Merge all layers with content for j in range(Global.canvas.layers.size() - 1, i, -1): if Global.canvas.layers[j][0].get_used_rect() != Rect2(0, 0, 0, 0): used_rect = used_rect.merge(Global.canvas.layers[j][0].get_used_rect()) - + #If no layer has any content, just return if used_rect == Rect2(0, 0, 0, 0): return - + #Loop through all the layers to crop them for j in range(Global.canvas.layers.size() - 1, -1, -1): var sprite := Image.new() @@ -173,7 +173,7 @@ func edit_menu_id_pressed(id : int) -> void: Global.canvas.layers[j][0] = sprite Global.canvas.layers[j][0].lock() Global.canvas.update_texture(j) - + var width = Global.canvas.layers[0][0].get_width() var height = Global.canvas.layers[0][0].get_height() Global.canvas.size = Vector2(width, height).floor() @@ -196,6 +196,10 @@ func edit_menu_id_pressed(id : int) -> void: canvas.layers[canvas.current_layer_index][0].flip_y() canvas.layers[canvas.current_layer_index][0].lock() canvas.update_texture(canvas.current_layer_index) + 5: #Undo + Global.undo_redo.undo() + 6: #Redo + Global.undo_redo.redo() func view_menu_id_pressed(id : int) -> void: match id: @@ -213,13 +217,13 @@ func help_menu_id_pressed(id : int) -> void: Global.can_draw = false func _on_CreateNewImage_confirmed() -> void: - var width := float($CreateNewImage/VBoxContainer/WidthCont/WidthValue.value) - var height := float($CreateNewImage/VBoxContainer/HeightCont/HeightValue.value) + var width = $CreateNewImage/VBoxContainer/WidthCont/WidthValue.value + var height = $CreateNewImage/VBoxContainer/HeightCont/HeightValue.value var fill_color : Color = $CreateNewImage/VBoxContainer/FillColor/FillColor.color clear_canvases() Global.canvas = load("res://Prefabs/Canvas.tscn").instance() Global.canvas.size = Vector2(width, height).floor() - + Global.canvas_parent.add_child(Global.canvas) Global.canvases.append(Global.canvas) Global.current_frame = 0 @@ -246,10 +250,10 @@ func _on_OpenSprite_file_selected(path) -> void: Global.canvas = canvas var width := file.get_16() var height := file.get_16() - + var layer := 0 var layer_line := file.get_line() - + while layer_line == "-": var buffer := file.get_buffer(width * height * 4) var image := Image.new() @@ -260,14 +264,14 @@ func _on_OpenSprite_file_selected(path) -> void: canvas.layers.append([image, tex, "Layer %s" % layer, true]) layer_line = file.get_line() layer += 1 - + canvas.size = Vector2(width, height) Global.canvases.append(canvas) canvas.frame = frame Global.canvas_parent.add_child(canvas) frame_line = file.get_line() frame += 1 - + Global.current_frame = frame - 1 #Load tool options Global.left_color_picker.color = file.get_var() @@ -282,11 +286,11 @@ func _on_OpenSprite_file_selected(path) -> void: Global.left_color_picker.get_picker().add_preset(color) for color in right_palette: Global.right_color_picker.get_picker().add_preset(color) - + #Load custom brushes Global.custom_brushes.clear() Global.remove_brush_buttons() - + var brush_line := file.get_line() while brush_line == "/": var b_width := file.get_16() @@ -297,7 +301,7 @@ func _on_OpenSprite_file_selected(path) -> void: Global.custom_brushes.append(image) Global.create_brush_button(image) brush_line = file.get_line() - + file.close() func _on_SaveSprite_file_selected(path) -> void: @@ -315,7 +319,7 @@ func _on_SaveSprite_file_selected(path) -> void: file.store_buffer(layer[0].get_data()) file.store_line("END_LAYERS") file.store_line("END_FRAMES") - + #Save tool options var left_color := Global.left_color_picker.color var right_color := Global.right_color_picker.color @@ -341,7 +345,7 @@ func _on_SaveSprite_file_selected(path) -> void: func _on_ImportSprites_files_selected(paths) -> void: if !import_as_new_frame.pressed: #If we're not adding a new frame, delete the previous clear_canvases() - + #Find the biggest image and let it handle the camera zoom options var max_size : Vector2 var biggest_canvas : Canvas @@ -369,10 +373,10 @@ func _on_ImportSprites_files_selected(paths) -> void: else: if canvas.size > max_size: biggest_canvas = canvas - + else: OS.alert("Can't load file") - + i += 1 Global.current_frame = i - 1 Global.canvas = Global.canvases[Global.canvases.size() - 1] @@ -385,7 +389,7 @@ func _on_ImportSprites_files_selected(paths) -> void: else: Global.remove_frame_button.disabled = true Global.remove_frame_button.mouse_default_cursor_shape = Control.CURSOR_FORBIDDEN - + func clear_canvases() -> void: for child in Global.vbox_layer_container.get_children(): if child is PanelContainer: @@ -454,7 +458,7 @@ func save_spritesheet() -> void: dst += Vector2(0, canvas.size.y) else: dst += Vector2(canvas.size.x, 0) - + var err = whole_image.save_png(current_export_path) if err != OK: OS.alert("Can't save file") @@ -468,7 +472,7 @@ func _on_ViewportContainer_mouse_entered() -> void: func _on_ViewportContainer_mouse_exited() -> void: Global.has_focus = false - + func _can_draw_true() -> void: Global.can_draw = true func _can_draw_false() -> void: @@ -486,8 +490,8 @@ func _on_Tool_pressed(tool_pressed : BaseButton, mouse_press := true, key_for_le tool_pressed.add_child(Global.right_indicator) func _on_ScaleImage_confirmed() -> void: - var width = float($ScaleImage/VBoxContainer/WidthCont/WidthValue.value) - var height = float($ScaleImage/VBoxContainer/HeightCont/HeightValue.value) + var width = $ScaleImage/VBoxContainer/WidthCont/WidthValue.value + var height = $ScaleImage/VBoxContainer/HeightCont/HeightValue.value for i in range(Global.canvas.layers.size() - 1, -1, -1): var sprite = Image.new() sprite = Global.canvas.layers[i][1].get_data() @@ -495,7 +499,7 @@ func _on_ScaleImage_confirmed() -> void: Global.canvas.layers[i][0] = sprite Global.canvas.layers[i][0].lock() Global.canvas.update_texture(i) - + Global.canvas.size = Vector2(width, height).floor() Global.canvas.camera_zoom() @@ -526,15 +530,15 @@ func _on_MoveDownLayer_pressed() -> void: func change_layer_order(rate : int) -> void: var change = Global.canvas.current_layer_index + rate - + var temp = Global.canvas.layers[Global.canvas.current_layer_index] Global.canvas.layers[Global.canvas.current_layer_index] = Global.canvas.layers[change] Global.canvas.layers[change] = temp - + Global.canvas.generate_layer_panels() Global.canvas.current_layer_index = change Global.canvas.get_layer_container(Global.canvas.current_layer_index).changed_selection() - + func _on_CloneLayer_pressed() -> void: add_layer(false) @@ -570,7 +574,7 @@ func _on_AddFrame_pressed() -> void: Global.canvases.append(canvas) Global.current_frame = Global.canvases.size() - 1 Global.canvas = canvas - + Global.canvas_parent.add_child(canvas) Global.remove_frame_button.disabled = false Global.remove_frame_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND @@ -614,7 +618,7 @@ func _on_CloneFrame_pressed() -> void: Global.canvases.append(canvas) Global.current_frame = Global.canvases.size() - 1 Global.canvas = canvas - + Global.canvas_parent.add_child(canvas) Global.remove_frame_button.disabled = false Global.remove_frame_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND @@ -630,21 +634,21 @@ func _on_MoveFrameRight_pressed() -> void: func change_frame_order(rate : int) -> void: var frame_button = Global.frame_container.get_node("Frame_%s" % Global.current_frame) var change = Global.current_frame + rate - + var temp = Global.canvases[Global.current_frame] Global.canvases[Global.current_frame] = Global.canvases[change] Global.canvases[change] = temp - + #Clear frame button names first, to avoid duplicates like two Frame_0s for canvas in Global.canvases: canvas.frame_button.name = "frame" - + for canvas in Global.canvases: canvas.frame = Global.canvases.find(canvas) canvas.frame_button.name = "Frame_%s" % canvas.frame canvas.frame_button.get_node("FrameButton").frame = canvas.frame canvas.frame_button.get_node("FrameID").text = str(canvas.frame + 1) - + Global.current_frame = change Global.frame_container.move_child(frame_button, Global.current_frame) Global.canvas_parent.move_child(Global.canvas, Global.current_frame) @@ -669,7 +673,7 @@ func _on_LoopAnim_pressed() -> void: func _on_PlayForward_toggled(button_pressed) -> void: Global.play_backwards.pressed = false Global.play_backwards.text = "Play Backwards" - + if button_pressed: Global.play_forward.text = "Stop" $AnimationTimer.wait_time = 1 / fps @@ -682,7 +686,7 @@ func _on_PlayForward_toggled(button_pressed) -> void: func _on_PlayBackwards_toggled(button_pressed) -> void: Global.play_forward.pressed = false Global.play_forward.text = "Play Forward" - + if button_pressed: Global.play_backwards.text = "Stop" $AnimationTimer.wait_time = 1 / fps @@ -709,7 +713,7 @@ func _on_AnimationTimer_timeout() -> void: 2: #Ping pong loop animation_forward = false _on_AnimationTimer_timeout() - + else: if Global.current_frame > 0: Global.current_frame -= 1 @@ -726,7 +730,7 @@ func _on_AnimationTimer_timeout() -> void: 2: #Ping pong loop animation_forward = true _on_AnimationTimer_timeout() - + Global.change_frame() func _on_FPSValue_value_changed(value) -> void: diff --git a/Scripts/SelectionRectangle.gd b/Scripts/SelectionRectangle.gd index 27386214f..17823d20c 100644 --- a/Scripts/SelectionRectangle.gd +++ b/Scripts/SelectionRectangle.gd @@ -12,7 +12,6 @@ var orig_colors := [] func _ready() -> void: img = Image.new() - #img.create(Global.canvas.size.x, Global.canvas.size.y, false, Image.FORMAT_RGBA8) img.create(1, 1, false, Image.FORMAT_RGBA8) img.lock() tex = ImageTexture.new() @@ -24,8 +23,9 @@ func _process(delta) -> void: var mouse_pos_floored := mouse_pos.floor() var start_pos := polygon[0] var end_pos := polygon[2] - var layer : Image = Global.canvas.layers[Global.canvas.current_layer_index][0] - + var current_layer_index := Global.canvas.current_layer_index + var layer : Image = Global.canvas.layers[current_layer_index][0] + if point_in_rectangle(mouse_pos, polygon[0], polygon[2]) && Global.selected_pixels.size() > 0 && (Global.current_left_tool == "RectSelect" || Global.current_right_tool == "RectSelect"): get_parent().get_parent().mouse_default_cursor_shape = Input.CURSOR_MOVE if (Global.current_left_tool == "RectSelect" && Input.is_action_just_pressed("left_mouse")) || (Global.current_right_tool == "RectSelect" && Input.is_action_just_pressed("right_mouse")): @@ -46,25 +46,25 @@ func _process(delta) -> void: for i in range(Global.selected_pixels.size()): var curr_px = Global.selected_pixels[i] if point_in_rectangle(curr_px, Global.canvas.location - Vector2.ONE, Global.canvas.size): - orig_colors.append(layer.get_pixelv(curr_px)) + orig_colors.append(layer.get_pixelv(curr_px)) #Color of pixel var px = curr_px - Global.selected_pixels[0] img.set_pixelv(px, orig_colors[i]) layer.set_pixelv(curr_px, Color(0, 0, 0, 0)) - else: + else: #If part of selection is outside canvas orig_colors.append(Color(0, 0, 0, 0)) Global.canvas.update_texture(Global.canvas.current_layer_index) tex.create_from_image(img, 0) update() else: get_parent().get_parent().mouse_default_cursor_shape = Input.CURSOR_CROSS - + if is_dragging: if (Global.current_left_tool == "RectSelect" && Input.is_action_pressed("left_mouse")) || (Global.current_right_tool == "RectSelect" && Input.is_action_pressed("right_mouse")): #Drag #if orig_x + mouse_pos_floored.x >= Global.canvas.location.x && diff_x + mouse_pos_floored.x <= Global.canvas.size.x: start_pos.x = orig_x + mouse_pos_floored.x end_pos.x = diff_x + mouse_pos_floored.x - + #if orig_y + mouse_pos_floored.y >= Global.canvas.location.y && diff_y + mouse_pos_floored.y <= Global.canvas.size.y: start_pos.y = orig_y + mouse_pos_floored.y end_pos.y = diff_y + mouse_pos_floored.y @@ -72,7 +72,7 @@ func _process(delta) -> void: polygon[1] = Vector2(end_pos.x, start_pos.y) polygon[2] = end_pos polygon[3] = Vector2(start_pos.x, end_pos.y) - + if (Global.current_left_tool == "RectSelect" && Input.is_action_just_released("left_mouse")) || (Global.current_right_tool == "RectSelect" && Input.is_action_just_released("right_mouse")): #Release Drag is_dragging = false @@ -86,13 +86,15 @@ func _process(delta) -> void: img.fill(Color(0, 0, 0, 0)) tex.create_from_image(img, 0) update() - + orig_colors.clear() Global.selected_pixels.clear() for xx in range(start_pos.x, end_pos.x): for yy in range(start_pos.y, end_pos.y): Global.selected_pixels.append(Vector2(xx, yy)) - + + Global.canvas.handle_redo("Rectangle Select") #Redo + #Handle copy if Input.is_action_just_pressed("copy") && Global.selected_pixels.size() > 0: Global.image_clipboard = layer.get_rect(Rect2(polygon[0], polygon[2] - polygon[0])) @@ -101,15 +103,16 @@ func _process(delta) -> void: brush_img = layer.get_rect(Rect2(polygon[0], polygon[2] - polygon[0])) brush_img = brush_img.get_rect(brush_img.get_used_rect()) #save only the visible pixels Global.custom_brushes.append(brush_img) - + Global.create_brush_button(brush_img) - + #Handle paste - #if Input.is_action_just_pressed("paste") && Global.selected_pixels.size() > 0 && !is_dragging: if Input.is_action_just_pressed("paste") && Global.selected_pixels.size() > 0 && Global.image_clipboard.get_size() > Vector2.ZERO: + Global.canvas.handle_undo("Draw") layer.blend_rect(Global.image_clipboard, Rect2(Vector2.ZERO, polygon[2]-polygon[0]), polygon[0]) layer.lock() - Global.canvas.update_texture(Global.canvas.current_layer_index) + Global.canvas.handle_redo("Draw") + #Global.canvas.update_texture(Global.canvas.current_layer_index) func _draw() -> void: if img.get_size() == polygon[2] - polygon[0]: @@ -117,4 +120,3 @@ func _draw() -> void: func point_in_rectangle(p : Vector2, coord1 : Vector2, coord2 : Vector2) -> bool: return p.x > coord1.x && p.y > coord1.y && p.x < coord2.x && p.y < coord2.y - \ No newline at end of file diff --git a/export_presets.cfg b/export_presets.cfg index 5f6ed0d0c..80bac5dfb 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -7,7 +7,7 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" -export_path="C:/Users/Overloaded/Dropbox/Orama Interactive/Projects/[Programa Labs]/Pixelorama/Stable/Pixelorama.exe" +export_path="C:/Users/Overloaded/Dropbox/Orama Interactive/Projects/[Programa Labs]/Pixelorama/Full of bugs/Pixelorama.exe" patch_list=PoolStringArray( ) script_export_mode=1 script_encryption_key="" diff --git a/project.godot b/project.godot index 115ce82e6..9e00cf6a3 100644 --- a/project.godot +++ b/project.godot @@ -131,16 +131,6 @@ right_lightdark_tool={ "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":true,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":85,"unicode":0,"echo":false,"script":null) ] } -flip_h={ -"deadzone": 0.5, -"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":true,"control":false,"meta":false,"command":false,"pressed":false,"scancode":72,"unicode":0,"echo":false,"script":null) - ] -} -flip_v={ -"deadzone": 0.5, -"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":true,"control":false,"meta":false,"command":false,"pressed":false,"scancode":86,"unicode":0,"echo":false,"script":null) - ] -} [rendering]