From 35f78cf02ceb34ba1106df977326c0ae6803955f Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Date: Tue, 26 Nov 2024 03:36:53 +0200 Subject: [PATCH] Refactor CelTileMap to eventually support alternative tiles Such as rotated and flipped tiles --- src/Classes/Cels/CelTileMap.gd | 82 ++++++++++++++++++--------- src/Tools/BaseTool.gd | 2 +- src/Tools/UtilityTools/ColorPicker.gd | 2 +- src/UI/Canvas/TileModeIndices.gd | 2 +- 4 files changed, 57 insertions(+), 31 deletions(-) diff --git a/src/Classes/Cels/CelTileMap.gd b/src/Classes/Cels/CelTileMap.gd index 57a295167..60981468a 100644 --- a/src/Classes/Cels/CelTileMap.gd +++ b/src/Classes/Cels/CelTileMap.gd @@ -8,12 +8,10 @@ var tileset: TileSetCustom: tileset.updated.disconnect(_on_tileset_updated) tileset = value if is_instance_valid(tileset): - indices_x = ceili(float(get_image().get_width()) / tileset.tile_size.x) - indices_y = ceili(float(get_image().get_height()) / tileset.tile_size.y) - indices.resize(indices_x * indices_y) + _resize_indices(get_image().get_size()) if not tileset.updated.is_connected(_on_tileset_updated): tileset.updated.connect(_on_tileset_updated) -var indices := PackedInt32Array() +var indices: Array[Tile] var indices_x: int var indices_y: int ## Dictionary of [int] and an [Array] of [bool] ([member TileSetPanel.placing_tiles]) @@ -27,6 +25,22 @@ var undo_redo_modes := {} var editing_images := {} +class Tile: + var index := 0 + var flip_h := false + var flip_v := false + var transpose := false + + func serialize() -> Dictionary: + return {"index": index, "flip_h": flip_h, "flip_v": flip_v, "transpose": transpose} + + func deserialize(dict: Dictionary) -> void: + index = dict.get("index", index) + flip_h = dict.get("flip_h", flip_h) + flip_v = dict.get("flip_v", flip_v) + transpose = dict.get("transpose", transpose) + + func _init(_tileset: TileSetCustom, _image: ImageExtended, _opacity := 1.0) -> void: super._init(_image, _opacity) tileset = _tileset @@ -35,7 +49,7 @@ func _init(_tileset: TileSetCustom, _image: ImageExtended, _opacity := 1.0) -> v func set_index(tile_position: int, index: int) -> void: index = clampi(index, 0, tileset.tiles.size() - 1) tileset.tiles[index].times_used += 1 - indices[tile_position] = index + indices[tile_position].index = index update_cel_portion(tile_position) Global.canvas.queue_redraw() @@ -52,11 +66,11 @@ func update_tileset(undo: bool) -> void: var coords := get_tile_coords(i) var rect := Rect2i(coords, tileset.tile_size) var image_portion := image.get_region(rect) - var index := indices[i] + var index := indices[i].index if index >= tileset.tiles.size(): printerr("Tile at position ", i, ", mapped to ", index, " is out of bounds!") index = 0 - indices[i] = 0 + indices[i].index = 0 var current_tile := tileset.tiles[index] if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL: if image_portion.is_invisible(): @@ -65,7 +79,7 @@ func update_tileset(undo: bool) -> void: # If the tileset is empty, only then add a new tile. if tileset.tiles.size() <= 1: tileset.add_tile(image_portion, self, tile_editing_mode) - indices[i] = tileset.tiles.size() - 1 + indices[i].index = tileset.tiles.size() - 1 continue if image_portion.get_data() != current_tile.image.get_data(): tileset.replace_tile_at(image_portion, index, self) @@ -78,12 +92,12 @@ func update_tileset(undo: bool) -> void: for j in range(1, tileset.tiles.size()): var tile := tileset.tiles[j] if image_portion.get_data() == tile.image.get_data(): - indices[i] = j + indices[i].index = j found_tile = true break if not found_tile: tileset.add_tile(image_portion, self, tile_editing_mode) - indices[i] = tileset.tiles.size() - 1 + indices[i].index = tileset.tiles.size() - 1 if undo: var tile_removed := tileset.remove_unused_tiles(self) if tile_removed: @@ -127,11 +141,11 @@ func update_tileset(undo: bool) -> void: ## The mapped tile does not exist in the tileset anymore. ## Simply replace the old tile with the new one, do not change its index. func handle_auto_editing_mode(i: int, image_portion: Image) -> void: - var index := indices[i] + var index := indices[i].index var current_tile := tileset.tiles[index] if image_portion.is_invisible(): # Case 0: The portion is transparent. - indices[i] = 0 + indices[i].index = 0 if index > 0: # Case 0.5: The portion is transparent and mapped to a tile. var is_removed := tileset.unuse_tile_at_index(index, self) @@ -145,12 +159,12 @@ func handle_auto_editing_mode(i: int, image_portion: Image) -> void: # Case 1: The portion is not mapped already, # and it exists in the tileset as a tile. tileset.tiles[index_in_tileset].times_used += 1 - indices[i] = index_in_tileset + indices[i].index = index_in_tileset else: # Case 2: The portion is not mapped already, # and it does not exist in the tileset. tileset.add_tile(image_portion, self, TileSetPanel.TileEditingMode.AUTO) - indices[i] = tileset.tiles.size() - 1 + indices[i].index = tileset.tiles.size() - 1 else: # If the portion is already mapped. if image_portion.get_data() == current_tile.image.get_data(): # Case 3: The portion is mapped and it did not change. @@ -161,13 +175,13 @@ func handle_auto_editing_mode(i: int, image_portion: Image) -> void: # Case 4: The portion is mapped and it exists in the tileset as a tile, # and the currently mapped tile still exists in the tileset. tileset.tiles[index_in_tileset].times_used += 1 - indices[i] = index_in_tileset + indices[i].index = index_in_tileset tileset.unuse_tile_at_index(index, self) else: # Case 5: The portion is mapped and it exists in the tileset as a tile, # and the currently mapped tile no longer exists in the tileset. tileset.tiles[index_in_tileset].times_used += 1 - indices[i] = index_in_tileset + indices[i].index = index_in_tileset tileset.remove_tile_at_index(index, self) # Re-index all indices that are after the deleted one. re_index_tiles_after_index(index) @@ -178,7 +192,7 @@ func handle_auto_editing_mode(i: int, image_portion: Image) -> void: # and the currently mapped tile still exists in the tileset. tileset.unuse_tile_at_index(index, self) tileset.add_tile(image_portion, self, TileSetPanel.TileEditingMode.AUTO) - indices[i] = tileset.tiles.size() - 1 + indices[i].index = tileset.tiles.size() - 1 else: # Case 7: The portion is mapped and it does not # exist in the tileset as a tile, @@ -190,16 +204,16 @@ func handle_auto_editing_mode(i: int, image_portion: Image) -> void: ## by reducing their value by one. func re_index_tiles_after_index(index: int) -> void: for i in indices.size(): - var tmp_index := indices[i] + var tmp_index := indices[i].index if tmp_index >= index: - indices[i] -= 1 + indices[i].index -= 1 func update_cel_portion(tile_position: int) -> void: var coords := get_tile_coords(tile_position) var rect := Rect2i(coords, tileset.tile_size) var image_portion := image.get_region(rect) - var index := indices[tile_position] + var index := indices[tile_position].index var current_tile := tileset.tiles[index] if image_portion.get_data() != current_tile.image.get_data(): var tile_size := current_tile.image.get_size() @@ -235,15 +249,23 @@ func re_index_all_tiles() -> void: var rect := Rect2i(coords, tileset.tile_size) var image_portion := image.get_region(rect) if image_portion.is_invisible(): - indices[i] = 0 + indices[i].index = 0 continue for j in range(1, tileset.tiles.size()): var tile := tileset.tiles[j] if image_portion.get_data() == tile.image.get_data(): - indices[i] = j + indices[i].index = j break +func _resize_indices(new_size: Vector2i) -> void: + indices_x = ceili(float(new_size.x) / tileset.tile_size.x) + indices_y = ceili(float(new_size.y) / tileset.tile_size.y) + indices.resize(indices_x * indices_y) + for i in indices.size(): + indices[i] = Tile.new() + + func _is_redo() -> bool: return Global.control.redone @@ -274,7 +296,7 @@ func update_texture(undo := false) -> void: return for i in indices.size(): - var index := indices[i] + var index := indices[i].index var coords := get_tile_coords(i) var rect := Rect2i(coords, tileset.tile_size) var image_portion := image.get_region(rect) @@ -299,9 +321,7 @@ func update_texture(undo := false) -> void: func size_changed(new_size: Vector2i) -> void: - indices_x = ceili(float(new_size.x) / tileset.tile_size.x) - indices_y = ceili(float(new_size.y) / tileset.tile_size.y) - indices.resize(indices_x * indices_y) + _resize_indices(new_size) re_index_all_tiles() @@ -319,13 +339,19 @@ func on_undo_redo(undo: bool) -> void: func serialize() -> Dictionary: var dict := super.serialize() - dict["tile_indices"] = indices + var tile_indices := [] + tile_indices.resize(indices.size()) + for i in tile_indices.size(): + tile_indices[i] = indices[i].serialize() + dict["tile_indices"] = tile_indices return dict func deserialize(dict: Dictionary) -> void: super.deserialize(dict) - indices = dict.get("tile_indices") + var tile_indices = dict.get("tile_indices") + for i in tile_indices.size(): + indices[i].deserialize(tile_indices[i]) func get_class_name() -> String: diff --git a/src/Tools/BaseTool.gd b/src/Tools/BaseTool.gd index 2ab088871..f54b73c7f 100644 --- a/src/Tools/BaseTool.gd +++ b/src/Tools/BaseTool.gd @@ -365,7 +365,7 @@ func _pick_color(pos: Vector2i) -> void: if is_placing_tiles(): var tile_position := get_tile_position(pos) var cel := Global.current_project.get_current_cel() as CelTileMap - Tools.selected_tile_index_changed.emit(cel.indices[tile_position]) + Tools.selected_tile_index_changed.emit(cel.indices[tile_position].index) return var image := Image.new() image.copy_from(_get_draw_image()) diff --git a/src/Tools/UtilityTools/ColorPicker.gd b/src/Tools/UtilityTools/ColorPicker.gd index d449fc0b1..11966bd5a 100644 --- a/src/Tools/UtilityTools/ColorPicker.gd +++ b/src/Tools/UtilityTools/ColorPicker.gd @@ -68,7 +68,7 @@ func _pick_color(pos: Vector2i) -> void: if is_placing_tiles(): var tile_position := get_tile_position(pos) var cel := Global.current_project.get_current_cel() as CelTileMap - Tools.selected_tile_index_changed.emit(cel.indices[tile_position]) + Tools.selected_tile_index_changed.emit(cel.indices[tile_position].index) return var image := Image.new() image.copy_from(_get_draw_image()) diff --git a/src/UI/Canvas/TileModeIndices.gd b/src/UI/Canvas/TileModeIndices.gd index 40c632071..2a130bd08 100644 --- a/src/UI/Canvas/TileModeIndices.gd +++ b/src/UI/Canvas/TileModeIndices.gd @@ -13,5 +13,5 @@ func _draw() -> void: for i in tilemap_cel.indices.size(): var pos := tilemap_cel.get_tile_coords(i) pos.y += tilemap_cel.tileset.tile_size.y - var text := str(tilemap_cel.indices[i]) + var text := str(tilemap_cel.indices[i].index) draw_string(Themes.get_font(), pos, text, HORIZONTAL_ALIGNMENT_LEFT, -1, 10)