mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-31 07:29:49 +00:00
[Undo/Redo] Compress most of the images stored in memory
Combinese62548517f
,4f5f37a522
,e22794e611
,9279a8e0ab
and2c5ece53dd
from the master branch.
This commit is contained in:
parent
6473febe78
commit
e0bd25c374
|
@ -432,10 +432,11 @@ func scale_image(width: int, height: int, interpolation: int) -> void:
|
|||
|
||||
for f in Global.current_project.frames:
|
||||
for i in range(f.cels.size() - 1, -1, -1):
|
||||
if not f.cels[i] is PixelCel:
|
||||
var cel: BaseCel = f.cels[i]
|
||||
if not cel is PixelCel:
|
||||
continue
|
||||
var sprite := Image.new()
|
||||
sprite.copy_from(f.cels[i].image)
|
||||
sprite.copy_from(cel.image)
|
||||
if interpolation == Interpolation.SCALE3X:
|
||||
var times: Vector2 = Vector2(
|
||||
ceil(width / (3.0 * sprite.get_width())),
|
||||
|
@ -454,10 +455,7 @@ func scale_image(width: int, height: int, interpolation: int) -> void:
|
|||
gen.generate_image(sprite, omniscale_shader, params, Vector2(width, height))
|
||||
else:
|
||||
sprite.resize(width, height, interpolation)
|
||||
Global.current_project.undo_redo.add_do_property(f.cels[i].image, "data", sprite.data)
|
||||
Global.current_project.undo_redo.add_undo_property(
|
||||
f.cels[i].image, "data", f.cels[i].image.data
|
||||
)
|
||||
Global.undo_redo_compress_images({cel.image: sprite.data}, {cel.image: cel.image.data})
|
||||
|
||||
general_undo_scale()
|
||||
|
||||
|
@ -487,8 +485,7 @@ func center(indices: Array) -> void:
|
|||
var sprite := Image.new()
|
||||
sprite.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
|
||||
sprite.blend_rect(cel.image, used_rect, offset)
|
||||
project.undo_redo.add_do_property(cel.image, "data", sprite.data)
|
||||
project.undo_redo.add_undo_property(cel.image, "data", cel.image.data)
|
||||
Global.undo_redo_compress_images({cel.image: sprite.data}, {cel.image: cel.image.data})
|
||||
project.undo_redo.add_undo_method(Global, "undo_or_redo", true)
|
||||
project.undo_redo.add_do_method(Global, "undo_or_redo", false)
|
||||
project.undo_redo.commit_action()
|
||||
|
@ -524,8 +521,7 @@ func crop_image() -> void:
|
|||
if not cel is PixelCel:
|
||||
continue
|
||||
var sprite: Image = cel.image.get_rect(used_rect)
|
||||
Global.current_project.undo_redo.add_do_property(cel.image, "data", sprite.data)
|
||||
Global.current_project.undo_redo.add_undo_property(cel.image, "data", cel.image.data)
|
||||
Global.undo_redo_compress_images({cel.image: sprite.data}, {cel.image: cel.image.data})
|
||||
|
||||
general_undo_scale()
|
||||
|
||||
|
@ -533,18 +529,17 @@ func crop_image() -> void:
|
|||
func resize_canvas(width: int, height: int, offset_x: int, offset_y: int) -> void:
|
||||
general_do_scale(width, height)
|
||||
for f in Global.current_project.frames:
|
||||
for c in f.cels:
|
||||
if not c is PixelCel:
|
||||
for cel in f.cels:
|
||||
if not cel is PixelCel:
|
||||
continue
|
||||
var sprite := Image.new()
|
||||
sprite.create(width, height, false, Image.FORMAT_RGBA8)
|
||||
sprite.blend_rect(
|
||||
c.image,
|
||||
cel.image,
|
||||
Rect2(Vector2.ZERO, Global.current_project.size),
|
||||
Vector2(offset_x, offset_y)
|
||||
)
|
||||
Global.current_project.undo_redo.add_do_property(c.image, "data", sprite.data)
|
||||
Global.current_project.undo_redo.add_undo_property(c.image, "data", c.image.data)
|
||||
Global.undo_redo_compress_images({cel.image: sprite.data}, {cel.image: cel.image.data})
|
||||
|
||||
general_undo_scale()
|
||||
|
||||
|
|
|
@ -480,7 +480,8 @@ func undo_or_redo(
|
|||
"Center Frames",
|
||||
"Merge Layer",
|
||||
"Link Cel",
|
||||
"Unlink Cel"
|
||||
"Unlink Cel",
|
||||
"Replaced Cel"
|
||||
]
|
||||
):
|
||||
if layer_index > -1 and frame_index > -1:
|
||||
|
@ -619,5 +620,44 @@ func convert_dictionary_values(dict: Dictionary) -> void:
|
|||
dict[key] = str2var("Vector3" + dict[key])
|
||||
|
||||
|
||||
func undo_redo_draw_op(image: Object, compressed_image_data: Dictionary, buffer_size: int) -> void:
|
||||
image["data"]["data"] = compressed_image_data["data"].decompress(buffer_size)
|
||||
func undo_redo_compress_images(redo_data: Dictionary, undo_data: Dictionary, project := current_project) -> void:
|
||||
for image in redo_data:
|
||||
if not image is Image:
|
||||
continue
|
||||
var new_image: Dictionary = redo_data[image]
|
||||
var new_size := Vector2(new_image["width"], new_image["height"])
|
||||
var buffer_size: int = new_image["data"].size()
|
||||
var compressed_data: PoolByteArray = new_image["data"].compress()
|
||||
project.undo_redo.add_do_method(
|
||||
self, "undo_redo_draw_op", image, new_size, compressed_data, buffer_size
|
||||
)
|
||||
image.unlock()
|
||||
for image in undo_data:
|
||||
if not image is Image:
|
||||
continue
|
||||
var new_image: Dictionary = undo_data[image]
|
||||
var new_size := Vector2(new_image["width"], new_image["height"])
|
||||
var buffer_size: int = new_image["data"].size()
|
||||
var compressed_data: PoolByteArray = new_image["data"].compress()
|
||||
project.undo_redo.add_undo_method(
|
||||
self, "undo_redo_draw_op", image, new_size, compressed_data, buffer_size
|
||||
)
|
||||
|
||||
|
||||
func undo_redo_draw_op(
|
||||
image: Image, new_size: Vector2, compressed_image_data: PoolByteArray, buffer_size: int
|
||||
) -> void:
|
||||
var decompressed := compressed_image_data.decompress(buffer_size)
|
||||
image.crop(new_size.x, new_size.y)
|
||||
image.data["data"] = decompressed
|
||||
|
||||
|
||||
|
||||
## Used by the Move tool for undo/redo, moves all of the Images in the images array
|
||||
## by diff pixels.
|
||||
func undo_redo_move(diff: Vector2, images: Array) -> void:
|
||||
for image in images:
|
||||
var image_copy := Image.new()
|
||||
image_copy.copy_from(image)
|
||||
image.fill(Color(0, 0, 0, 0))
|
||||
image.blit_rect(image_copy, Rect2(Vector2.ZERO, image.get_size()), diff)
|
||||
|
|
|
@ -544,8 +544,9 @@ func open_image_at_cel(image: Image, layer_index := 0, frame_index := 0) -> void
|
|||
cel_image.create(project_width, project_height, false, Image.FORMAT_RGBA8)
|
||||
cel_image.blit_rect(image, Rect2(Vector2.ZERO, image.get_size()), Vector2.ZERO)
|
||||
var cel: PixelCel = project.frames[i].cels[layer_index]
|
||||
project.undo_redo.add_do_property(cel, "image", cel_image)
|
||||
project.undo_redo.add_undo_property(cel, "image", cel.image)
|
||||
Global.undo_redo_compress_images(
|
||||
{cel.image: cel_image.data}, {cel.image: cel.image.data}, project
|
||||
)
|
||||
|
||||
project.undo_redo.add_do_property(project, "selected_cels", [])
|
||||
project.undo_redo.add_do_method(project, "change_cel", frame_index, layer_index)
|
||||
|
|
|
@ -152,10 +152,7 @@ func _commit_undo(action: String, undo_data: Dictionary, project: Project) -> vo
|
|||
var redo_data := _get_undo_data(project)
|
||||
project.undos += 1
|
||||
project.undo_redo.create_action(action)
|
||||
for image in redo_data:
|
||||
project.undo_redo.add_do_property(image, "data", redo_data[image])
|
||||
for image in undo_data:
|
||||
project.undo_redo.add_undo_property(image, "data", undo_data[image])
|
||||
Global.undo_redo_compress_images(redo_data, undo_data, project)
|
||||
project.undo_redo.add_do_method(Global, "undo_or_redo", false, -1, -1, project)
|
||||
project.undo_redo.add_undo_method(Global, "undo_or_redo", true, -1, -1, project)
|
||||
project.undo_redo.commit_action()
|
||||
|
|
|
@ -156,5 +156,5 @@ visible = false
|
|||
[connection signal="custom_action" from="Dialogs/QuitAndSaveDialog" to="." method="_on_QuitAndSaveDialog_custom_action"]
|
||||
[connection signal="popup_hide" from="Dialogs/QuitAndSaveDialog" to="." method="_can_draw_true"]
|
||||
[connection signal="popup_hide" from="Dialogs/ErrorDialog" to="." method="_can_draw_true"]
|
||||
[connection signal="popup_hide" from="Dialogs/BackupConfirmation" to="." method="_on_BackupConfirmation_popup_hide"]
|
||||
[connection signal="popup_hide" from="Dialogs/BackupConfirmation" to="." method="_can_draw_true"]
|
||||
[connection signal="popup_hide" from="Dialogs/BackupConfirmation" to="." method="_on_BackupConfirmation_popup_hide"]
|
||||
|
|
|
@ -485,11 +485,7 @@ func commit_undo(action: String, undo_data: Dictionary) -> void:
|
|||
|
||||
project.undos += 1
|
||||
project.undo_redo.create_action(action)
|
||||
for image in redo_data:
|
||||
project.undo_redo.add_do_property(image, "data", redo_data[image])
|
||||
image.unlock()
|
||||
for image in undo_data:
|
||||
project.undo_redo.add_undo_property(image, "data", undo_data[image])
|
||||
Global.undo_redo_compress_images(redo_data, undo_data, project)
|
||||
project.undo_redo.add_do_method(Global, "undo_or_redo", false, frame, layer)
|
||||
project.undo_redo.add_undo_method(Global, "undo_or_redo", true, frame, layer)
|
||||
project.undo_redo.commit_action()
|
||||
|
|
|
@ -209,21 +209,7 @@ func commit_undo() -> void:
|
|||
layer = project.current_layer
|
||||
|
||||
project.undos += 1
|
||||
for image in redo_data:
|
||||
var compressed_data = redo_data[image]
|
||||
var buffer_size = compressed_data["data"].size()
|
||||
compressed_data["data"] = compressed_data["data"].compress()
|
||||
project.undo_redo.add_do_method(
|
||||
Global, "undo_redo_draw_op", image, compressed_data, buffer_size
|
||||
)
|
||||
image.unlock()
|
||||
for image in _undo_data:
|
||||
var compressed_data = _undo_data[image]
|
||||
var buffer_size = compressed_data["data"].size()
|
||||
compressed_data["data"] = compressed_data["data"].compress()
|
||||
project.undo_redo.add_undo_method(
|
||||
Global, "undo_redo_draw_op", image, compressed_data, buffer_size
|
||||
)
|
||||
Global.undo_redo_compress_images(redo_data, _undo_data, project)
|
||||
project.undo_redo.add_do_method(Global, "undo_or_redo", false, frame, layer)
|
||||
project.undo_redo.add_undo_method(Global, "undo_or_redo", true, frame, layer)
|
||||
project.undo_redo.commit_action()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
extends BaseTool
|
||||
|
||||
var _undo_data := {}
|
||||
var _start_pos: Vector2
|
||||
var _offset: Vector2
|
||||
|
||||
|
@ -42,7 +41,6 @@ func draw_start(position: Vector2) -> void:
|
|||
return
|
||||
_start_pos = position
|
||||
_offset = position
|
||||
_undo_data = _get_undo_data()
|
||||
if Global.current_project.has_selection:
|
||||
selection_node.transform_content_start()
|
||||
_content_transformation_check = selection_node.is_moving_content
|
||||
|
@ -83,14 +81,7 @@ func draw_end(position: Vector2) -> void:
|
|||
else:
|
||||
var pixel_diff: Vector2 = position - _start_pos
|
||||
Global.canvas.move_preview_location = Vector2.ZERO
|
||||
var images := _get_selected_draw_images()
|
||||
for image in images:
|
||||
var image_copy := Image.new()
|
||||
image_copy.copy_from(image)
|
||||
image.fill(Color(0, 0, 0, 0))
|
||||
image.blit_rect(image_copy, Rect2(Vector2.ZERO, project.size), pixel_diff)
|
||||
|
||||
commit_undo("Draw")
|
||||
commit_undo("Draw", pixel_diff)
|
||||
|
||||
_start_pos = Vector2.INF
|
||||
_snap_to_grid = false
|
||||
|
@ -123,45 +114,18 @@ func _snap_position(position: Vector2) -> Vector2:
|
|||
return position
|
||||
|
||||
|
||||
func commit_undo(action: String) -> void:
|
||||
var redo_data := _get_undo_data()
|
||||
func commit_undo(action: String, diff: Vector2) -> void:
|
||||
var project: Project = Global.current_project
|
||||
var frame := -1
|
||||
var layer := -1
|
||||
if Global.animation_timer.is_stopped() and project.selected_cels.size() == 1:
|
||||
frame = project.current_frame
|
||||
layer = project.current_layer
|
||||
|
||||
var images := _get_selected_draw_images()
|
||||
project.undos += 1
|
||||
project.undo_redo.create_action(action)
|
||||
for image in redo_data:
|
||||
project.undo_redo.add_do_property(image, "data", redo_data[image])
|
||||
image.unlock()
|
||||
for image in _undo_data:
|
||||
project.undo_redo.add_undo_property(image, "data", _undo_data[image])
|
||||
project.undo_redo.add_do_method(Global, "undo_redo_move", diff, images)
|
||||
project.undo_redo.add_do_method(Global, "undo_or_redo", false, frame, layer)
|
||||
project.undo_redo.add_undo_method(Global, "undo_redo_move", -diff, images)
|
||||
project.undo_redo.add_undo_method(Global, "undo_or_redo", true, frame, layer)
|
||||
project.undo_redo.commit_action()
|
||||
|
||||
_undo_data.clear()
|
||||
|
||||
|
||||
func _get_undo_data() -> Dictionary:
|
||||
var data := {}
|
||||
var project: Project = Global.current_project
|
||||
var cels := [] # Array of Cels
|
||||
if Global.animation_timer.is_stopped():
|
||||
for cel_index in project.selected_cels:
|
||||
cels.append(project.frames[cel_index[0]].cels[cel_index[1]])
|
||||
else:
|
||||
for frame in project.frames:
|
||||
var cel: PixelCel = frame.cels[project.current_layer]
|
||||
cels.append(cel)
|
||||
for cel in cels:
|
||||
if not cel is PixelCel:
|
||||
continue
|
||||
var image: Image = cel.image
|
||||
image.unlock()
|
||||
data[image] = image.data
|
||||
image.lock()
|
||||
return data
|
||||
|
|
|
@ -55,31 +55,27 @@ func _commit_undo(action: String, undo_data: Dictionary, project: Project) -> vo
|
|||
var redo_data := _get_undo_data(project)
|
||||
project.undos += 1
|
||||
project.undo_redo.create_action(action)
|
||||
Global.undo_redo_compress_images(redo_data, undo_data, project)
|
||||
if redo_data.has("outline_offset"):
|
||||
project.undo_redo.add_do_property(project, "selection_map", redo_data["selection_map"])
|
||||
project.undo_redo.add_do_property(project, "selection_offset", redo_data["outline_offset"])
|
||||
project.undo_redo.add_undo_property(project, "selection_map", undo_data["selection_map"])
|
||||
project.undo_redo.add_undo_property(project, "selection_offset", undo_data["outline_offset"])
|
||||
|
||||
for image in redo_data:
|
||||
if not image is Image:
|
||||
continue
|
||||
project.undo_redo.add_do_property(image, "data", redo_data[image])
|
||||
image.unlock()
|
||||
for image in undo_data:
|
||||
if not image is Image:
|
||||
continue
|
||||
project.undo_redo.add_undo_property(image, "data", undo_data[image])
|
||||
project.undo_redo.add_do_method(Global, "undo_or_redo", false, -1, -1, project)
|
||||
project.undo_redo.add_undo_property(
|
||||
project, "selection_offset", undo_data["outline_offset"]
|
||||
)
|
||||
project.undo_redo.add_do_method(project, "selection_map_changed")
|
||||
project.undo_redo.add_undo_method(Global, "undo_or_redo", true, -1, -1, project)
|
||||
project.undo_redo.add_undo_method(project, "selection_map_changed")
|
||||
project.undo_redo.add_do_method(Global, "undo_or_redo", false, -1, -1, project)
|
||||
project.undo_redo.add_undo_method(Global, "undo_or_redo", true, -1, -1, project)
|
||||
project.undo_redo.commit_action()
|
||||
|
||||
|
||||
func _get_undo_data(project: Project) -> Dictionary:
|
||||
var affect_selection := selection_checkbox.pressed and project.has_selection
|
||||
var data := {}
|
||||
if affect_selection:
|
||||
var bitmap_image := SelectionMap.new()
|
||||
bitmap_image.copy_from(project.selection_map)
|
||||
var data := {}
|
||||
data["selection_map"] = bitmap_image
|
||||
data["outline_offset"] = project.selection_offset
|
||||
|
||||
|
@ -87,7 +83,6 @@ func _get_undo_data(project: Project) -> Dictionary:
|
|||
for image in images:
|
||||
image.unlock()
|
||||
data[image] = image.data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
|
|
|
@ -870,8 +870,11 @@ func _on_MergeDownLayer_pressed() -> void:
|
|||
project.undo_redo.add_do_property(bottom_cel, "image", bottom_image)
|
||||
project.undo_redo.add_undo_property(bottom_cel, "image", bottom_cel.image)
|
||||
else:
|
||||
project.undo_redo.add_do_property(bottom_cel.image, "data", bottom_image.data)
|
||||
project.undo_redo.add_undo_property(bottom_cel.image, "data", bottom_cel.image.data)
|
||||
Global.undo_redo_compress_images(
|
||||
{bottom_cel.image: bottom_image.data},
|
||||
{bottom_cel.image: bottom_cel.image.data},
|
||||
project
|
||||
)
|
||||
|
||||
project.undo_redo.add_do_method(project, "remove_layers", [top_layer.index])
|
||||
project.undo_redo.add_undo_method(
|
||||
|
|
Loading…
Reference in a new issue