mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-19 09:39:48 +00:00
Resizing should now work
Also fixes cel replacing
This commit is contained in:
parent
a3324591be
commit
5e34faf793
|
@ -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,13 +548,13 @@ 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):
|
|
||||||
var cel := f.cels[i]
|
|
||||||
if not cel is PixelCel:
|
if not cel is PixelCel:
|
||||||
continue
|
continue
|
||||||
var cel_image := (cel as PixelCel).get_image()
|
var cel_image := (cel as PixelCel).get_image()
|
||||||
var sprite := _resize_image(cel_image, width, height, interpolation) as ImageExtended
|
var sprite := _resize_image(cel_image, width, height, interpolation) as ImageExtended
|
||||||
|
if cel is CelTileMap:
|
||||||
|
(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)
|
||||||
|
|
||||||
|
@ -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,8 +621,7 @@ 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()
|
||||||
|
@ -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)
|
||||||
|
|
|
@ -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 := []
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue