UndoRedo for border moving

Nothing else in the selections system works properly in UndoRedo right now. Needs:

- UR support for creating selections
- UR support for modifying selections (merging and cutting selections together)
- UR support for removing selection
- UR support for moving content

& for all the rest of the remaining features
This commit is contained in:
Manolis Papadeas 2021-02-25 01:38:00 +02:00
parent 4574c9b60d
commit 76575a1c80
4 changed files with 110 additions and 77 deletions

View file

@ -10,7 +10,6 @@ func draw_start(position : Vector2) -> void:
offset = position offset = position
if Global.current_project.selected_pixels: if Global.current_project.selected_pixels:
Global.canvas.selection.move_content_start() Global.canvas.selection.move_content_start()
# Global.selection_rectangl.move_start(true)
func draw_move(position : Vector2) -> void: func draw_move(position : Vector2) -> void:

View file

@ -33,6 +33,7 @@ func draw_start(position : Vector2) -> void:
_move = true _move = true
_offset = position _offset = position
start_position = position start_position = position
Global.canvas.selection.move_borders_start()
_set_cursor_text(selection.get_rect()) _set_cursor_text(selection.get_rect())
# if Global.selection_rectangle.has_point(position): # if Global.selection_rectangle.has_point(position):
# _move = true # _move = true

View file

@ -7,8 +7,8 @@ var local_selected_pixels := [] setget _local_selected_pixels_changed # Array of
var local_image := Image.new() var local_image := Image.new()
var local_image_texture := ImageTexture.new() var local_image_texture := ImageTexture.new()
var clear_selection_on_tree_exit := true var clear_selection_on_tree_exit := true
var temp_polygon : PoolVector2Array setget _temp_polygon_changed
var _selected_rect := Rect2(0, 0, 0, 0) var _selected_rect := Rect2(0, 0, 0, 0)
var _clipped_rect := Rect2(0, 0, 0, 0)
var _move_image := Image.new() var _move_image := Image.new()
var _move_texture := ImageTexture.new() var _move_texture := ImageTexture.new()
var _clear_image := Image.new() var _clear_image := Image.new()
@ -152,6 +152,11 @@ func _local_selected_pixels_changed(value : Array) -> void:
# Global.canvas.get_node("Selection").generate_polygons() # Global.canvas.get_node("Selection").generate_polygons()
func _temp_polygon_changed(value : PoolVector2Array) -> void:
temp_polygon = value
polygon = temp_polygon
func has_point(position : Vector2) -> bool: func has_point(position : Vector2) -> bool:
return Geometry.is_point_in_polygon(position, polygon) return Geometry.is_point_in_polygon(position, polygon)
@ -311,80 +316,51 @@ func copy() -> void:
project.brushes.append(brush) project.brushes.append(brush)
Brushes.add_project_brush(brush) Brushes.add_project_brush(brush)
func cut() -> void: # This is basically the same as copy + delete #func cut() -> void: # This is basically the same as copy + delete
if _selected_rect.has_no_area(): # if _selected_rect.has_no_area():
return # return
#
var undo_data = _get_undo_data(true) # var undo_data = _get_undo_data(true)
var project := Global.current_project # var project := Global.current_project
var image : Image = project.frames[project.current_frame].cels[project.current_layer].image # var image : Image = project.frames[project.current_frame].cels[project.current_layer].image
var size := _selected_rect.size # var size := _selected_rect.size
var rect = Rect2(Vector2.ZERO, size) # var rect = Rect2(Vector2.ZERO, size)
_clipboard = image.get_rect(_selected_rect) # _clipboard = image.get_rect(_selected_rect)
if _clipboard.is_invisible(): # if _clipboard.is_invisible():
return # return
#
_clear_image.resize(size.x, size.y, Image.INTERPOLATE_NEAREST) # _clear_image.resize(size.x, size.y, Image.INTERPOLATE_NEAREST)
var brush = _clipboard.get_rect(_clipboard.get_used_rect()) # var brush = _clipboard.get_rect(_clipboard.get_used_rect())
project.brushes.append(brush) # project.brushes.append(brush)
Brushes.add_project_brush(brush) # Brushes.add_project_brush(brush)
# move_end() # The selection_rectangle can be used while is moving, this prevents malfunctioning ## move_end() # The selection_rectangle can be used while is moving, this prevents malfunctioning
image.blit_rect(_clear_image, rect, _selected_rect.position) # image.blit_rect(_clear_image, rect, _selected_rect.position)
commit_undo("Draw", undo_data) # commit_undo("Draw", undo_data)
#
func paste() -> void: #func paste() -> void:
if _clipboard.get_size() <= Vector2.ZERO: # if _clipboard.get_size() <= Vector2.ZERO:
return # return
#
var undo_data = _get_undo_data(true) # var undo_data = _get_undo_data(true)
var project := Global.current_project # var project := Global.current_project
var image : Image = project.frames[project.current_frame].cels[project.current_layer].image # var image : Image = project.frames[project.current_frame].cels[project.current_layer].image
var size := _selected_rect.size # var size := _selected_rect.size
var rect = Rect2(Vector2.ZERO, size) # var rect = Rect2(Vector2.ZERO, size)
image.blend_rect(_clipboard, rect, _selected_rect.position) # image.blend_rect(_clipboard, rect, _selected_rect.position)
# move_end() # The selection_rectangle can be used while is moving, this prevents malfunctioning ## move_end() # The selection_rectangle can be used while is moving, this prevents malfunctioning
commit_undo("Draw", undo_data) # commit_undo("Draw", undo_data)
#
#
func delete() -> void: #func delete() -> void:
var undo_data = _get_undo_data(true) # var undo_data = _get_undo_data(true)
var project := Global.current_project # var project := Global.current_project
var image : Image = project.frames[project.current_frame].cels[project.current_layer].image # var image : Image = project.frames[project.current_frame].cels[project.current_layer].image
var size := _selected_rect.size # var size := _selected_rect.size
var rect = Rect2(Vector2.ZERO, size) # var rect = Rect2(Vector2.ZERO, size)
_clear_image.resize(size.x, size.y, Image.INTERPOLATE_NEAREST) # _clear_image.resize(size.x, size.y, Image.INTERPOLATE_NEAREST)
image.blit_rect(_clear_image, rect, _selected_rect.position) # image.blit_rect(_clear_image, rect, _selected_rect.position)
# move_end() # The selection_rectangle can be used while is moving, this prevents malfunctioning ## move_end() # The selection_rectangle can be used while is moving, this prevents malfunctioning
commit_undo("Draw", undo_data) # commit_undo("Draw", undo_data)
func commit_undo(action : String, undo_data : Dictionary) -> void:
var redo_data = _get_undo_data("image_data" in undo_data)
var project := Global.current_project
project.undos += 1
project.undo_redo.create_action(action)
project.undo_redo.add_do_property(project, "selected_rect", redo_data["selected_rect"])
project.undo_redo.add_undo_property(project, "selected_rect", undo_data["selected_rect"])
if "image_data" in undo_data:
var image : Image = project.frames[project.current_frame].cels[project.current_layer].image
project.undo_redo.add_do_property(image, "data", redo_data["image_data"])
project.undo_redo.add_undo_property(image, "data", undo_data["image_data"])
project.undo_redo.add_do_method(Global, "redo", project.current_frame, project.current_layer)
project.undo_redo.add_undo_method(Global, "undo", project.current_frame, project.current_layer)
project.undo_redo.commit_action()
func _get_undo_data(undo_image : bool) -> Dictionary:
var data = {}
var project := Global.current_project
data["selected_rect"] = Global.current_project.selected_rect
if undo_image:
var image : Image = project.frames[project.current_frame].cels[project.current_layer].image
image.unlock()
data["image_data"] = image.data
image.lock()
return data
func _on_SelectionShape_tree_exiting() -> void: func _on_SelectionShape_tree_exiting() -> void:

View file

@ -9,25 +9,37 @@ extends Node2D
# var selected_pixels := [] # Array of Vector2s - the selected pixels # var selected_pixels := [] # Array of Vector2s - the selected pixels
func move_borders_start() -> void:
for shape in get_children():
shape.temp_polygon = shape.polygon
func move_borders(move : Vector2) -> void: func move_borders(move : Vector2) -> void:
for shape in get_children(): for shape in get_children():
shape._selected_rect.position += move shape._selected_rect.position += move
shape._clipped_rect.position += move
for i in shape.polygon.size(): for i in shape.polygon.size():
shape.polygon[i] += move shape.polygon[i] += move
func move_borders_end(new_pos : Vector2, old_pos : Vector2) -> void: func move_borders_end(new_pos : Vector2, old_pos : Vector2) -> void:
# for shape in get_children():
# var diff := new_pos - old_pos
# for i in shape.polygon.size():
# shape.polygon[i] -= diff # Temporarily set the polygon back to be used for undoredo
var undo_data = _get_undo_data(false)
for shape in get_children(): for shape in get_children():
shape.temp_polygon = shape.polygon
var diff := new_pos - old_pos var diff := new_pos - old_pos
var selected_pixels_copy = shape.local_selected_pixels.duplicate() var selected_pixels_copy = shape.local_selected_pixels.duplicate()
for i in selected_pixels_copy.size(): for i in selected_pixels_copy.size():
selected_pixels_copy[i] += diff selected_pixels_copy[i] += diff
shape.local_selected_pixels = selected_pixels_copy shape.local_selected_pixels = selected_pixels_copy
commit_undo("Rectangle Select", undo_data)
func move_content_start() -> void: func move_content_start() -> void:
move_borders_start()
for shape in get_children(): for shape in get_children():
if !shape.local_image.is_empty(): if !shape.local_image.is_empty():
return return
@ -52,6 +64,51 @@ func move_content_end() -> void:
shape.local_image_texture = ImageTexture.new() shape.local_image_texture = ImageTexture.new()
func commit_undo(action : String, undo_data : Dictionary) -> void:
var redo_data = _get_undo_data("image_data" in undo_data)
var project := Global.current_project
project.undos += 1
project.undo_redo.create_action(action)
var i := 0
for shape in get_children():
project.undo_redo.add_do_property(shape, "temp_polygon", redo_data["temp_polygon_%s" % i])
project.undo_redo.add_do_property(shape, "_selected_rect", redo_data["_selected_rect_%s" % i])
project.undo_redo.add_do_property(shape, "local_selected_pixels", redo_data["local_selected_pixels_%s" % i])
project.undo_redo.add_undo_property(shape, "temp_polygon", undo_data["temp_polygon_%s" % i])
project.undo_redo.add_undo_property(shape, "_selected_rect", undo_data["_selected_rect_%s" % i])
project.undo_redo.add_undo_property(shape, "local_selected_pixels", undo_data["local_selected_pixels_%s" % i])
i += 1
if "image_data" in undo_data:
var image : Image = project.frames[project.current_frame].cels[project.current_layer].image
project.undo_redo.add_do_property(image, "data", redo_data["image_data"])
project.undo_redo.add_undo_property(image, "data", undo_data["image_data"])
project.undo_redo.add_do_method(Global, "redo", project.current_frame, project.current_layer)
project.undo_redo.add_undo_method(Global, "undo", project.current_frame, project.current_layer)
project.undo_redo.commit_action()
func _get_undo_data(undo_image : bool) -> Dictionary:
var data = {}
var project := Global.current_project
var i := 0
for shape in get_children():
data["temp_polygon_%s" % i] = shape.temp_polygon
data["_selected_rect_%s" % i] = shape._selected_rect
data["local_selected_pixels_%s" % i] = shape.local_selected_pixels
i += 1
# data["selected_rect"] = Global.current_project.selected_rect
if undo_image:
var image : Image = project.frames[project.current_frame].cels[project.current_layer].image
image.unlock()
data["image_data"] = image.data
image.lock()
for d in data.keys():
print(d, data[d])
return data
func generate_rect(pixels : Array) -> Rect2: func generate_rect(pixels : Array) -> Rect2:
if !pixels: if !pixels:
return Rect2() return Rect2()