mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-19 01:29:49 +00:00
Refactor CelTileMap to eventually support alternative tiles
Such as rotated and flipped tiles
This commit is contained in:
parent
610d2deb27
commit
a696db3fc0
|
@ -8,12 +8,10 @@ var tileset: TileSetCustom:
|
||||||
tileset.updated.disconnect(_on_tileset_updated)
|
tileset.updated.disconnect(_on_tileset_updated)
|
||||||
tileset = value
|
tileset = value
|
||||||
if is_instance_valid(tileset):
|
if is_instance_valid(tileset):
|
||||||
indices_x = ceili(float(get_image().get_width()) / tileset.tile_size.x)
|
_resize_indices(get_image().get_size())
|
||||||
indices_y = ceili(float(get_image().get_height()) / tileset.tile_size.y)
|
|
||||||
indices.resize(indices_x * indices_y)
|
|
||||||
if not tileset.updated.is_connected(_on_tileset_updated):
|
if not tileset.updated.is_connected(_on_tileset_updated):
|
||||||
tileset.updated.connect(_on_tileset_updated)
|
tileset.updated.connect(_on_tileset_updated)
|
||||||
var indices := PackedInt32Array()
|
var indices: Array[Tile]
|
||||||
var indices_x: int
|
var indices_x: int
|
||||||
var indices_y: int
|
var indices_y: int
|
||||||
## Dictionary of [int] and an [Array] of [bool] ([member TileSetPanel.placing_tiles])
|
## Dictionary of [int] and an [Array] of [bool] ([member TileSetPanel.placing_tiles])
|
||||||
|
@ -27,6 +25,22 @@ var undo_redo_modes := {}
|
||||||
var editing_images := {}
|
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:
|
func _init(_tileset: TileSetCustom, _image: ImageExtended, _opacity := 1.0) -> void:
|
||||||
super._init(_image, _opacity)
|
super._init(_image, _opacity)
|
||||||
tileset = _tileset
|
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:
|
func set_index(tile_position: int, index: int) -> void:
|
||||||
index = clampi(index, 0, tileset.tiles.size() - 1)
|
index = clampi(index, 0, tileset.tiles.size() - 1)
|
||||||
tileset.tiles[index].times_used += 1
|
tileset.tiles[index].times_used += 1
|
||||||
indices[tile_position] = index
|
indices[tile_position].index = index
|
||||||
update_cel_portion(tile_position)
|
update_cel_portion(tile_position)
|
||||||
Global.canvas.queue_redraw()
|
Global.canvas.queue_redraw()
|
||||||
|
|
||||||
|
@ -52,11 +66,11 @@ func update_tileset(undo: bool) -> void:
|
||||||
var coords := get_tile_coords(i)
|
var coords := get_tile_coords(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 := image.get_region(rect)
|
||||||
var index := indices[i]
|
var index := indices[i].index
|
||||||
if index >= tileset.tiles.size():
|
if index >= tileset.tiles.size():
|
||||||
printerr("Tile at position ", i, ", mapped to ", index, " is out of bounds!")
|
printerr("Tile at position ", i, ", mapped to ", index, " is out of bounds!")
|
||||||
index = 0
|
index = 0
|
||||||
indices[i] = 0
|
indices[i].index = 0
|
||||||
var current_tile := tileset.tiles[index]
|
var current_tile := tileset.tiles[index]
|
||||||
if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL:
|
if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL:
|
||||||
if image_portion.is_invisible():
|
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 the tileset is empty, only then add a new tile.
|
||||||
if tileset.tiles.size() <= 1:
|
if tileset.tiles.size() <= 1:
|
||||||
tileset.add_tile(image_portion, self, tile_editing_mode)
|
tileset.add_tile(image_portion, self, tile_editing_mode)
|
||||||
indices[i] = tileset.tiles.size() - 1
|
indices[i].index = tileset.tiles.size() - 1
|
||||||
continue
|
continue
|
||||||
if image_portion.get_data() != current_tile.image.get_data():
|
if image_portion.get_data() != current_tile.image.get_data():
|
||||||
tileset.replace_tile_at(image_portion, index, self)
|
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()):
|
for j in range(1, tileset.tiles.size()):
|
||||||
var tile := tileset.tiles[j]
|
var tile := tileset.tiles[j]
|
||||||
if image_portion.get_data() == tile.image.get_data():
|
if image_portion.get_data() == tile.image.get_data():
|
||||||
indices[i] = j
|
indices[i].index = j
|
||||||
found_tile = true
|
found_tile = true
|
||||||
break
|
break
|
||||||
if not found_tile:
|
if not found_tile:
|
||||||
tileset.add_tile(image_portion, self, tile_editing_mode)
|
tileset.add_tile(image_portion, self, tile_editing_mode)
|
||||||
indices[i] = tileset.tiles.size() - 1
|
indices[i].index = tileset.tiles.size() - 1
|
||||||
if undo:
|
if undo:
|
||||||
var tile_removed := tileset.remove_unused_tiles(self)
|
var tile_removed := tileset.remove_unused_tiles(self)
|
||||||
if tile_removed:
|
if tile_removed:
|
||||||
|
@ -127,11 +141,11 @@ func update_tileset(undo: bool) -> void:
|
||||||
## The mapped tile does not exist in the tileset anymore.
|
## The mapped tile does not exist in the tileset anymore.
|
||||||
## Simply replace the old tile with the new one, do not change its index.
|
## 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:
|
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]
|
var current_tile := tileset.tiles[index]
|
||||||
if image_portion.is_invisible():
|
if image_portion.is_invisible():
|
||||||
# Case 0: The portion is transparent.
|
# Case 0: The portion is transparent.
|
||||||
indices[i] = 0
|
indices[i].index = 0
|
||||||
if index > 0:
|
if index > 0:
|
||||||
# Case 0.5: The portion is transparent and mapped to a tile.
|
# Case 0.5: The portion is transparent and mapped to a tile.
|
||||||
var is_removed := tileset.unuse_tile_at_index(index, self)
|
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,
|
# Case 1: The portion is not mapped already,
|
||||||
# and it exists in the tileset as a tile.
|
# and it exists in the tileset as a tile.
|
||||||
tileset.tiles[index_in_tileset].times_used += 1
|
tileset.tiles[index_in_tileset].times_used += 1
|
||||||
indices[i] = index_in_tileset
|
indices[i].index = index_in_tileset
|
||||||
else:
|
else:
|
||||||
# Case 2: The portion is not mapped already,
|
# Case 2: The portion is not mapped already,
|
||||||
# and it does not exist in the tileset.
|
# and it does not exist in the tileset.
|
||||||
tileset.add_tile(image_portion, self, TileSetPanel.TileEditingMode.AUTO)
|
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.
|
else: # If the portion is already mapped.
|
||||||
if image_portion.get_data() == current_tile.image.get_data():
|
if image_portion.get_data() == current_tile.image.get_data():
|
||||||
# Case 3: The portion is mapped and it did not change.
|
# 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,
|
# 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.
|
# and the currently mapped tile still exists in the tileset.
|
||||||
tileset.tiles[index_in_tileset].times_used += 1
|
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)
|
tileset.unuse_tile_at_index(index, self)
|
||||||
else:
|
else:
|
||||||
# Case 5: The portion is mapped and it exists in the tileset as a tile,
|
# 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.
|
# and the currently mapped tile no longer exists in the tileset.
|
||||||
tileset.tiles[index_in_tileset].times_used += 1
|
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)
|
tileset.remove_tile_at_index(index, self)
|
||||||
# Re-index all indices that are after the deleted one.
|
# Re-index all indices that are after the deleted one.
|
||||||
re_index_tiles_after_index(index)
|
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.
|
# and the currently mapped tile still exists in the tileset.
|
||||||
tileset.unuse_tile_at_index(index, self)
|
tileset.unuse_tile_at_index(index, self)
|
||||||
tileset.add_tile(image_portion, self, TileSetPanel.TileEditingMode.AUTO)
|
tileset.add_tile(image_portion, self, TileSetPanel.TileEditingMode.AUTO)
|
||||||
indices[i] = tileset.tiles.size() - 1
|
indices[i].index = tileset.tiles.size() - 1
|
||||||
else:
|
else:
|
||||||
# Case 7: The portion is mapped and it does not
|
# Case 7: The portion is mapped and it does not
|
||||||
# exist in the tileset as a tile,
|
# 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.
|
## by reducing their value by one.
|
||||||
func re_index_tiles_after_index(index: int) -> void:
|
func re_index_tiles_after_index(index: int) -> void:
|
||||||
for i in indices.size():
|
for i in indices.size():
|
||||||
var tmp_index := indices[i]
|
var tmp_index := indices[i].index
|
||||||
if tmp_index >= index:
|
if tmp_index >= index:
|
||||||
indices[i] -= 1
|
indices[i].index -= 1
|
||||||
|
|
||||||
|
|
||||||
func update_cel_portion(tile_position: int) -> void:
|
func update_cel_portion(tile_position: int) -> void:
|
||||||
var coords := get_tile_coords(tile_position)
|
var coords := get_tile_coords(tile_position)
|
||||||
var rect := Rect2i(coords, tileset.tile_size)
|
var rect := Rect2i(coords, tileset.tile_size)
|
||||||
var image_portion := image.get_region(rect)
|
var image_portion := image.get_region(rect)
|
||||||
var index := indices[tile_position]
|
var index := indices[tile_position].index
|
||||||
var current_tile := tileset.tiles[index]
|
var current_tile := tileset.tiles[index]
|
||||||
if image_portion.get_data() != current_tile.image.get_data():
|
if image_portion.get_data() != current_tile.image.get_data():
|
||||||
var tile_size := current_tile.image.get_size()
|
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 rect := Rect2i(coords, tileset.tile_size)
|
||||||
var image_portion := image.get_region(rect)
|
var image_portion := image.get_region(rect)
|
||||||
if image_portion.is_invisible():
|
if image_portion.is_invisible():
|
||||||
indices[i] = 0
|
indices[i].index = 0
|
||||||
continue
|
continue
|
||||||
for j in range(1, tileset.tiles.size()):
|
for j in range(1, tileset.tiles.size()):
|
||||||
var tile := tileset.tiles[j]
|
var tile := tileset.tiles[j]
|
||||||
if image_portion.get_data() == tile.image.get_data():
|
if image_portion.get_data() == tile.image.get_data():
|
||||||
indices[i] = j
|
indices[i].index = j
|
||||||
break
|
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:
|
func _is_redo() -> bool:
|
||||||
return Global.control.redone
|
return Global.control.redone
|
||||||
|
|
||||||
|
@ -274,7 +296,7 @@ func update_texture(undo := false) -> void:
|
||||||
return
|
return
|
||||||
|
|
||||||
for i in indices.size():
|
for i in indices.size():
|
||||||
var index := indices[i]
|
var index := indices[i].index
|
||||||
var coords := get_tile_coords(i)
|
var coords := get_tile_coords(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 := image.get_region(rect)
|
||||||
|
@ -299,9 +321,7 @@ func update_texture(undo := false) -> void:
|
||||||
|
|
||||||
|
|
||||||
func size_changed(new_size: Vector2i) -> void:
|
func size_changed(new_size: Vector2i) -> void:
|
||||||
indices_x = ceili(float(new_size.x) / tileset.tile_size.x)
|
_resize_indices(new_size)
|
||||||
indices_y = ceili(float(new_size.y) / tileset.tile_size.y)
|
|
||||||
indices.resize(indices_x * indices_y)
|
|
||||||
re_index_all_tiles()
|
re_index_all_tiles()
|
||||||
|
|
||||||
|
|
||||||
|
@ -319,13 +339,19 @@ func on_undo_redo(undo: bool) -> void:
|
||||||
|
|
||||||
func serialize() -> Dictionary:
|
func serialize() -> Dictionary:
|
||||||
var dict := super.serialize()
|
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
|
return dict
|
||||||
|
|
||||||
|
|
||||||
func deserialize(dict: Dictionary) -> void:
|
func deserialize(dict: Dictionary) -> void:
|
||||||
super.deserialize(dict)
|
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:
|
func get_class_name() -> String:
|
||||||
|
|
|
@ -365,7 +365,7 @@ func _pick_color(pos: Vector2i) -> void:
|
||||||
if is_placing_tiles():
|
if is_placing_tiles():
|
||||||
var tile_position := get_tile_position(pos)
|
var tile_position := get_tile_position(pos)
|
||||||
var cel := Global.current_project.get_current_cel() as CelTileMap
|
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
|
return
|
||||||
var image := Image.new()
|
var image := Image.new()
|
||||||
image.copy_from(_get_draw_image())
|
image.copy_from(_get_draw_image())
|
||||||
|
|
|
@ -68,7 +68,7 @@ func _pick_color(pos: Vector2i) -> void:
|
||||||
if is_placing_tiles():
|
if is_placing_tiles():
|
||||||
var tile_position := get_tile_position(pos)
|
var tile_position := get_tile_position(pos)
|
||||||
var cel := Global.current_project.get_current_cel() as CelTileMap
|
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
|
return
|
||||||
var image := Image.new()
|
var image := Image.new()
|
||||||
image.copy_from(_get_draw_image())
|
image.copy_from(_get_draw_image())
|
||||||
|
|
|
@ -13,5 +13,5 @@ func _draw() -> void:
|
||||||
for i in tilemap_cel.indices.size():
|
for i in tilemap_cel.indices.size():
|
||||||
var pos := tilemap_cel.get_tile_coords(i)
|
var pos := tilemap_cel.get_tile_coords(i)
|
||||||
pos.y += tilemap_cel.tileset.tile_size.y
|
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)
|
draw_string(Themes.get_font(), pos, text, HORIZONTAL_ALIGNMENT_LEFT, -1, 10)
|
||||||
|
|
Loading…
Reference in a new issue