1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-19 01:29:49 +00:00

Resizing should now work

Also fixes cel replacing
This commit is contained in:
Emmanouil Papadeas 2024-11-29 13:57:21 +02:00
parent a3324591be
commit 5e34faf793
4 changed files with 80 additions and 42 deletions

View file

@ -535,9 +535,11 @@ func center(indices: Array) -> void:
tmp_centered.blend_rect(cel.image, used_rect, offset) tmp_centered.blend_rect(cel.image, used_rect, offset)
var centered := ImageExtended.new() var centered := ImageExtended.new()
centered.copy_from_custom(tmp_centered, cel_image.is_indexed) centered.copy_from_custom(tmp_centered, cel_image.is_indexed)
if cel is CelTileMap:
(cel as CelTileMap).serialize_undo_data_source_image(centered, redo_data, undo_data)
centered.add_data_to_dictionary(redo_data, cel_image) centered.add_data_to_dictionary(redo_data, cel_image)
cel_image.add_data_to_dictionary(undo_data) cel_image.add_data_to_dictionary(undo_data)
Global.undo_redo_compress_images(redo_data, undo_data) project.deserialize_cel_undo_data(redo_data, undo_data)
project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true)) project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true))
project.undo_redo.add_do_method(Global.undo_or_redo.bind(false)) project.undo_redo.add_do_method(Global.undo_or_redo.bind(false))
project.undo_redo.commit_action() project.undo_redo.commit_action()
@ -546,15 +548,15 @@ func center(indices: Array) -> void:
func scale_project(width: int, height: int, interpolation: int) -> void: func scale_project(width: int, height: int, interpolation: int) -> void:
var redo_data := {} var redo_data := {}
var undo_data := {} var undo_data := {}
for f in Global.current_project.frames: for cel in Global.current_project.get_all_pixel_cels():
for i in range(f.cels.size() - 1, -1, -1): if not cel is PixelCel:
var cel := f.cels[i] continue
if not cel is PixelCel: var cel_image := (cel as PixelCel).get_image()
continue var sprite := _resize_image(cel_image, width, height, interpolation) as ImageExtended
var cel_image := (cel as PixelCel).get_image() if cel is CelTileMap:
var sprite := _resize_image(cel_image, width, height, interpolation) as ImageExtended (cel as CelTileMap).serialize_undo_data_source_image(sprite, redo_data, undo_data)
sprite.add_data_to_dictionary(redo_data, cel_image) sprite.add_data_to_dictionary(redo_data, cel_image)
cel_image.add_data_to_dictionary(undo_data) cel_image.add_data_to_dictionary(undo_data)
general_do_and_undo_scale(width, height, redo_data, undo_data) general_do_and_undo_scale(width, height, redo_data, undo_data)
@ -596,9 +598,9 @@ func _resize_image(
func crop_to_selection() -> void: func crop_to_selection() -> void:
if not Global.current_project.has_selection: if not Global.current_project.has_selection:
return return
Global.canvas.selection.transform_content_confirm()
var redo_data := {} var redo_data := {}
var undo_data := {} var undo_data := {}
Global.canvas.selection.transform_content_confirm()
var rect: Rect2i = Global.canvas.selection.big_bounding_rectangle var rect: Rect2i = Global.canvas.selection.big_bounding_rectangle
# Loop through all the cels to crop them # Loop through all the cels to crop them
for cel in Global.current_project.get_all_pixel_cels(): for cel in Global.current_project.get_all_pixel_cels():
@ -606,6 +608,8 @@ func crop_to_selection() -> void:
var tmp_cropped := cel_image.get_region(rect) var tmp_cropped := cel_image.get_region(rect)
var cropped := ImageExtended.new() var cropped := ImageExtended.new()
cropped.copy_from_custom(tmp_cropped, cel_image.is_indexed) cropped.copy_from_custom(tmp_cropped, cel_image.is_indexed)
if cel is CelTileMap:
(cel as CelTileMap).serialize_undo_data_source_image(cropped, redo_data, undo_data)
cropped.add_data_to_dictionary(redo_data, cel_image) cropped.add_data_to_dictionary(redo_data, cel_image)
cel_image.add_data_to_dictionary(undo_data) cel_image.add_data_to_dictionary(undo_data)
@ -617,18 +621,17 @@ func crop_to_selection() -> void:
func crop_to_content() -> void: func crop_to_content() -> void:
Global.canvas.selection.transform_content_confirm() Global.canvas.selection.transform_content_confirm()
var used_rect := Rect2i() var used_rect := Rect2i()
for f in Global.current_project.frames: for cel in Global.current_project.get_all_pixel_cels():
for cel in f.cels: if not cel is PixelCel:
if not cel is PixelCel: continue
continue var cel_used_rect := cel.get_image().get_used_rect()
var cel_used_rect := cel.get_image().get_used_rect() if cel_used_rect == Rect2i(0, 0, 0, 0): # If the cel has no content
if cel_used_rect == Rect2i(0, 0, 0, 0): # If the cel has no content continue
continue
if used_rect == Rect2i(0, 0, 0, 0): # If we still haven't found the first cel with content if used_rect == Rect2i(0, 0, 0, 0): # If we still haven't found the first cel with content
used_rect = cel_used_rect used_rect = cel_used_rect
else: else:
used_rect = used_rect.merge(cel_used_rect) used_rect = used_rect.merge(cel_used_rect)
# If no layer has any content, just return # If no layer has any content, just return
if used_rect == Rect2i(0, 0, 0, 0): if used_rect == Rect2i(0, 0, 0, 0):
@ -644,6 +647,8 @@ func crop_to_content() -> void:
var tmp_cropped := cel_image.get_region(used_rect) var tmp_cropped := cel_image.get_region(used_rect)
var cropped := ImageExtended.new() var cropped := ImageExtended.new()
cropped.copy_from_custom(tmp_cropped, cel_image.is_indexed) cropped.copy_from_custom(tmp_cropped, cel_image.is_indexed)
if cel is CelTileMap:
(cel as CelTileMap).serialize_undo_data_source_image(cropped, redo_data, undo_data)
cropped.add_data_to_dictionary(redo_data, cel_image) cropped.add_data_to_dictionary(redo_data, cel_image)
cel_image.add_data_to_dictionary(undo_data) cel_image.add_data_to_dictionary(undo_data)
@ -662,6 +667,8 @@ func resize_canvas(width: int, height: int, offset_x: int, offset_y: int) -> voi
cel_image, Rect2i(Vector2i.ZERO, cel_image.get_size()), Vector2i(offset_x, offset_y) cel_image, Rect2i(Vector2i.ZERO, cel_image.get_size()), Vector2i(offset_x, offset_y)
) )
resized.convert_rgb_to_indexed() resized.convert_rgb_to_indexed()
if cel is CelTileMap:
(cel as CelTileMap).serialize_undo_data_source_image(resized, redo_data, undo_data)
resized.add_data_to_dictionary(redo_data, cel_image) resized.add_data_to_dictionary(redo_data, cel_image)
cel_image.add_data_to_dictionary(undo_data) cel_image.add_data_to_dictionary(undo_data)
@ -698,7 +705,7 @@ func general_do_and_undo_scale(
project.undo_redo.add_do_property(project, "y_symmetry_point", new_y_symmetry_point) project.undo_redo.add_do_property(project, "y_symmetry_point", new_y_symmetry_point)
project.undo_redo.add_do_property(project.x_symmetry_axis, "points", new_x_symmetry_axis_points) project.undo_redo.add_do_property(project.x_symmetry_axis, "points", new_x_symmetry_axis_points)
project.undo_redo.add_do_property(project.y_symmetry_axis, "points", new_y_symmetry_axis_points) project.undo_redo.add_do_property(project.y_symmetry_axis, "points", new_y_symmetry_axis_points)
Global.undo_redo_compress_images(redo_data, undo_data) project.deserialize_cel_undo_data(redo_data, undo_data)
project.undo_redo.add_undo_property(project, "size", project.size) project.undo_redo.add_undo_property(project, "size", project.size)
project.undo_redo.add_undo_property(project, "x_symmetry_point", project.x_symmetry_point) project.undo_redo.add_undo_property(project, "x_symmetry_point", project.x_symmetry_point)
project.undo_redo.add_undo_property(project, "y_symmetry_point", project.y_symmetry_point) project.undo_redo.add_undo_property(project, "y_symmetry_point", project.y_symmetry_point)

View file

@ -156,13 +156,14 @@ func transform_tile(
return transformed_tile return transformed_tile
func update_tileset() -> void: func update_tileset(
tile_editing_mode := TileSetPanel.tile_editing_mode, source_image := image
) -> void:
editing_images.clear() editing_images.clear()
var tile_editing_mode := TileSetPanel.tile_editing_mode
for i in cells.size(): for i in cells.size():
var coords := get_cell_coords_in_image(i) var coords := get_cell_coords_in_image(i)
var rect := Rect2i(coords, tileset.tile_size) var rect := Rect2i(coords, tileset.tile_size)
var image_portion := image.get_region(rect) var image_portion := source_image.get_region(rect)
var index := cells[i].index var index := cells[i].index
if index >= tileset.tiles.size(): if index >= tileset.tiles.size():
printerr("Cell at position ", i + 1, ", mapped to ", index, " is out of bounds!") printerr("Cell at position ", i + 1, ", mapped to ", index, " is out of bounds!")
@ -416,11 +417,6 @@ func update_texture(undo := false) -> void:
super.update_texture(undo) super.update_texture(undo)
func size_changed(new_size: Vector2i) -> void:
_resize_cells(new_size)
_re_index_all_cells()
func serialize_undo_data() -> Dictionary: func serialize_undo_data() -> Dictionary:
var dict := {} var dict := {}
var cell_indices := [] var cell_indices := []
@ -432,22 +428,39 @@ func serialize_undo_data() -> Dictionary:
return dict return dict
func serialize_undo_data_source_image(
source_image: ImageExtended, redo_data: Dictionary, undo_data: Dictionary
) -> void:
undo_data[self] = serialize_undo_data()
if source_image.get_size() != image.get_size():
_resize_cells(source_image.get_size())
tileset.clear_tileset(self)
var tile_editing_mode := TileSetPanel.tile_editing_mode
if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL:
tile_editing_mode = TileSetPanel.TileEditingMode.AUTO
update_tileset(tile_editing_mode, source_image)
redo_data[self] = serialize_undo_data()
func deserialize_undo_data(dict: Dictionary, undo_redo: UndoRedo, undo: bool) -> void: func deserialize_undo_data(dict: Dictionary, undo_redo: UndoRedo, undo: bool) -> void:
var cell_indices = dict["cell_indices"] var cell_indices = dict["cell_indices"]
if undo: if undo:
for i in cell_indices.size(): undo_redo.add_undo_method(deserialize_cell_data.bind(cell_indices))
var cell_data: Dictionary = cell_indices[i]
undo_redo.add_undo_method(cells[i].deserialize.bind(cell_data))
if dict.has("tileset"): if dict.has("tileset"):
undo_redo.add_undo_method(tileset.deserialize_undo_data.bind(dict.tileset, self)) undo_redo.add_undo_method(tileset.deserialize_undo_data.bind(dict.tileset, self))
else: else:
for i in cell_indices.size(): undo_redo.add_do_method(deserialize_cell_data.bind(cell_indices))
var cell_data: Dictionary = cell_indices[i]
undo_redo.add_do_method(cells[i].deserialize.bind(cell_data))
if dict.has("tileset"): if dict.has("tileset"):
undo_redo.add_do_method(tileset.deserialize_undo_data.bind(dict.tileset, self)) undo_redo.add_do_method(tileset.deserialize_undo_data.bind(dict.tileset, self))
func deserialize_cell_data(cell_indices: Array) -> void:
_resize_cells(image.get_size())
for i in cell_indices.size():
var cell_data: Dictionary = cell_indices[i]
cells[i].deserialize(cell_data)
func serialize() -> Dictionary: func serialize() -> Dictionary:
var dict := super.serialize() var dict := super.serialize()
var cell_indices := [] var cell_indices := []

View file

@ -2,8 +2,8 @@ class_name TileSetCustom
extends RefCounted extends RefCounted
## A Tileset is a collection of tiles, used by [LayerTileMap]s and [CelTileMap]s. ## A Tileset is a collection of tiles, used by [LayerTileMap]s and [CelTileMap]s.
## The tileset contains the [Project] that it is being used by, its [member name]. ## The tileset contains its [member name], the size of each individual tile,
## the size of each individual tile, and the collection of [TileSetCustom.Tile]s itself. ## and the collection of [TileSetCustom.Tile]s itself.
## Not to be confused with [TileSet], which is a Godot class. ## Not to be confused with [TileSet], which is a Godot class.
## Emitted every time the tileset changes, such as when a tile is added, removed or replaced. ## Emitted every time the tileset changes, such as when a tile is added, removed or replaced.
@ -16,6 +16,11 @@ var name := ""
var tile_size: Vector2i var tile_size: Vector2i
## The collection of tiles in the form of an [Array] of type [TileSetCustom.Tile]. ## The collection of tiles in the form of an [Array] of type [TileSetCustom.Tile].
var tiles: Array[Tile] = [] var tiles: Array[Tile] = []
## If [code]true[/code], the code in [method clear_tileset] does not execute.
## This variable is used to prevent multiple cels from clearing the tileset at the same time.
## In [method clear_tileset], the variable is set to [code]true[/code], and then
## immediately set to [code]false[/code] in the next frame using [method Object.set_deferred].
var _tileset_has_been_cleared := false
## An internal class of [TileSetCustom], which contains data used by individual tiles of a tileset. ## An internal class of [TileSetCustom], which contains data used by individual tiles of a tileset.
@ -109,6 +114,19 @@ func remove_unused_tiles(cel: CelTileMap) -> bool:
return tile_removed return tile_removed
## Clears the tileset. Usually called when the project gets resized,
## and tilemap cels are updating their size and clearing the tileset to re-create it.
func clear_tileset(cel: CelTileMap) -> void:
if _tileset_has_been_cleared:
return
tiles.clear()
var empty_image := Image.create_empty(tile_size.x, tile_size.y, false, Image.FORMAT_RGBA8)
tiles.append(Tile.new(empty_image))
updated.emit(cel)
_tileset_has_been_cleared = true
set_deferred("_tileset_has_been_cleared", false)
## Serializes the data of this class into the form of a [Dictionary], ## Serializes the data of this class into the form of a [Dictionary],
## which is used so the data can be stored in pxo files. ## which is used so the data can be stored in pxo files.
func serialize() -> Dictionary: func serialize() -> Dictionary:

View file

@ -1107,9 +1107,9 @@ func _on_MergeDownLayer_pressed() -> void:
var undo_data := {} var undo_data := {}
var redo_data := {} var redo_data := {}
if bottom_cel is CelTileMap: if bottom_cel is CelTileMap:
undo_data[bottom_cel] = (bottom_cel as CelTileMap).serialize_undo_data() (bottom_cel as CelTileMap).serialize_undo_data_source_image(
(bottom_cel as CelTileMap).update_tileset(new_bottom_image) new_bottom_image, redo_data, undo_data
redo_data[bottom_cel] = (bottom_cel as CelTileMap).serialize_undo_data() )
new_bottom_image.add_data_to_dictionary(redo_data, bottom_image) new_bottom_image.add_data_to_dictionary(redo_data, bottom_image)
bottom_image.add_data_to_dictionary(undo_data) bottom_image.add_data_to_dictionary(undo_data)
project.deserialize_cel_undo_data(redo_data, undo_data) project.deserialize_cel_undo_data(redo_data, undo_data)