From c60c62f4764f09659592fae5e3f1dc74baeb4e7b Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Date: Fri, 27 Dec 2024 03:30:56 +0200 Subject: [PATCH] Fix tileset being completely cleared when resizing a project Now only remove the tiles that are used so they can be remade as resized tiles. Unused tiles remain in the tileset as is. --- src/Autoload/OpenSave.gd | 9 ++++++--- src/Classes/Cels/CelTileMap.gd | 9 ++++++++- src/Classes/TileSetCustom.gd | 18 ++++++++++-------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 064afa546..97397a6e8 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -287,7 +287,10 @@ func open_pxo_file(path: String, is_backup := false, replace_empty := true) -> v var image := Image.create_from_data( tile_size.x, tile_size.y, false, new_project.get_image_format(), image_data ) - tileset.add_tile(image, null) + tileset.add_tile(image, null, 0) + for cel in new_project.get_all_pixel_cels(): + if cel is CelTileMap: + cel.find_times_used_of_tiles() zip_reader.close() new_project.export_directory_path = path.get_base_dir() @@ -878,7 +881,7 @@ func open_image_as_tileset( Rect2i(frame_width * xx, frame_height * yy, frame_width, frame_height) ) @warning_ignore("int_as_enum_without_cast") - tileset.add_tile(cropped_image, null) + tileset.add_tile(cropped_image, null, 0) project.tilesets.append(tileset) @@ -901,7 +904,7 @@ func open_image_as_tileset_smart( ) cropped_image.blit_rect(image, rect, offset) @warning_ignore("int_as_enum_without_cast") - tileset.add_tile(cropped_image, null) + tileset.add_tile(cropped_image, null, 0) project.tilesets.append(tileset) diff --git a/src/Classes/Cels/CelTileMap.gd b/src/Classes/Cels/CelTileMap.gd index 4d0275679..6a4ef10ce 100644 --- a/src/Classes/Cels/CelTileMap.gd +++ b/src/Classes/Cels/CelTileMap.gd @@ -330,7 +330,7 @@ func serialize_undo_data_source_image( if source_image.get_size() != image.get_size(): undo_data[self]["resize"] = true _resize_cells(source_image.get_size()) - tileset.clear_tileset(self) + tileset.handle_project_resize(self) var tile_editing_mode := TileSetPanel.tile_editing_mode if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL: tile_editing_mode = TileSetPanel.TileEditingMode.AUTO @@ -352,6 +352,13 @@ func deserialize_undo_data(dict: Dictionary, undo_redo: UndoRedo, undo: bool) -> undo_redo.add_do_method(tileset.deserialize_undo_data.bind(dict.tileset, self)) +## Called when loading a new project. Loops through all [member cells] +## and finds the amount of times each tile from the [member tileset] is being used. +func find_times_used_of_tiles() -> void: + for cell in cells: + tileset.tiles[cell.index].times_used += 1 + + ## Gets called every time a change is being applied to the [param image], ## such as when finishing drawing with a draw tool, or when applying an image effect. ## This method responsible for updating the indices of the [member cells], as well as diff --git a/src/Classes/TileSetCustom.gd b/src/Classes/TileSetCustom.gd index dd6aeb451..39eb7dbcb 100644 --- a/src/Classes/TileSetCustom.gd +++ b/src/Classes/TileSetCustom.gd @@ -16,9 +16,9 @@ var name := "" var tile_size: Vector2i ## The collection of tiles in the form of an [Array] of type [TileSetCustom.Tile]. var tiles: Array[Tile] = [] -## If [code]true[/code], the code in [method clear_tileset] does not execute. +## If [code]true[/code], the code in [method handle_project_resize] 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 +## In [method handle_project_resize], 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 @@ -50,8 +50,9 @@ func _init(_tile_size: Vector2i, _name := "", add_empty_tile := true) -> void: ## Adds a new [param image] as a tile to the tileset. ## The [param cel] parameter references the [CelTileMap] that this change is coming from, ## and the [param edit_mode] parameter contains the tile editing mode at the time of this change. -func add_tile(image: Image, cel: CelTileMap) -> void: +func add_tile(image: Image, cel: CelTileMap, times_used := 1) -> void: var tile := Tile.new(image) + tile.times_used = times_used tiles.append(tile) updated.emit(cel, -1) @@ -115,14 +116,15 @@ func remove_unused_tiles(cel: CelTileMap) -> bool: return tile_removed -## Clears the tileset. Usually called when the project gets resized, +## Clears the used tiles of tileset. 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: +func handle_project_resize(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)) + for i in range(tiles.size() - 1, 0, -1): + var tile := tiles[i] + if tile.times_used > 0: + tiles.erase(tile) updated.emit(cel, -1) _tileset_has_been_cleared = true set_deferred("_tileset_has_been_cleared", false)