mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-31 07:29:49 +00:00
Properly implement the auto tile editing mode
Should work well now.
This commit is contained in:
parent
d584807c14
commit
29262ff7da
|
@ -16,35 +16,13 @@ func _init(_tileset: TileSetCustom, _image: ImageExtended, _opacity := 1.0) -> v
|
|||
|
||||
|
||||
func update_tileset() -> void:
|
||||
var removed_tile_indices: Array[int] = []
|
||||
if TileSetPanel.tile_editing_mode == TileSetPanel.TileEditingMode.AUTO:
|
||||
for j in range(tileset.tiles.size() - 1, 0, -1):
|
||||
var tile := tileset.tiles[j]
|
||||
if tile.mode_added == TileSetPanel.TileEditingMode.STACK:
|
||||
# Don't delete tiles that have been added using the stack mode.
|
||||
continue
|
||||
var tile_used := false
|
||||
for i in indices.size():
|
||||
var x_coord := float(tileset.tile_size.x) * (i % indices_x)
|
||||
var y_coord := float(tileset.tile_size.y) * (i / indices_x)
|
||||
var rect := Rect2i(Vector2i(x_coord, y_coord), tileset.tile_size)
|
||||
var image_portion := image.get_region(rect)
|
||||
if image_portion.is_invisible():
|
||||
continue
|
||||
if image_portion.get_data() == tile.image.get_data():
|
||||
tile_used = true
|
||||
break
|
||||
if not tile_used:
|
||||
removed_tile_indices.append(j)
|
||||
tileset.remove_tile_at_index(j)
|
||||
for i in indices.size():
|
||||
var x_coord := float(tileset.tile_size.x) * (i % indices_x)
|
||||
var y_coord := float(tileset.tile_size.y) * (i / indices_x)
|
||||
var rect := Rect2i(Vector2i(x_coord, y_coord), tileset.tile_size)
|
||||
var image_portion := image.get_region(rect)
|
||||
if image_portion.is_invisible():
|
||||
continue
|
||||
var index := indices[i]
|
||||
var current_tile := tileset.tiles[index]
|
||||
if TileSetPanel.tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL:
|
||||
if index == 0 or tileset.tiles.size() <= index:
|
||||
if tileset.tiles.size() <= 1:
|
||||
|
@ -54,7 +32,9 @@ func update_tileset() -> void:
|
|||
if image_portion.get_data() != tileset.tiles[index].image.get_data():
|
||||
tileset.replace_tile_at(image_portion, index)
|
||||
# TODO: Update the rest of the tilemap
|
||||
else: # Auto or stack
|
||||
elif TileSetPanel.tile_editing_mode == TileSetPanel.TileEditingMode.AUTO:
|
||||
handle_auto_editing_mode(i, image_portion)
|
||||
else: # Stack
|
||||
var found_tile := false
|
||||
for j in range(1, tileset.tiles.size()):
|
||||
var tile := tileset.tiles[j]
|
||||
|
@ -63,15 +43,131 @@ func update_tileset() -> void:
|
|||
found_tile = true
|
||||
break
|
||||
if not found_tile:
|
||||
if removed_tile_indices.is_empty():
|
||||
tileset.add_tile(image_portion, TileSetPanel.tile_editing_mode)
|
||||
indices[i] = tileset.tiles.size() - 1
|
||||
else:
|
||||
var index_position := removed_tile_indices.pop_back() as int
|
||||
tileset.insert_tile(
|
||||
image_portion, index_position, TileSetPanel.tile_editing_mode
|
||||
)
|
||||
indices[i] = index_position
|
||||
tileset.add_tile(image_portion, TileSetPanel.tile_editing_mode)
|
||||
indices[i] = tileset.tiles.size() - 1
|
||||
|
||||
|
||||
## Cases:[br]
|
||||
## 0) Portion is transparent. Set its index to 0.
|
||||
## [br]
|
||||
## 0.5) Portion is transparent and mapped.
|
||||
## Set its index to 0 and unuse the mapped tile.
|
||||
## If the mapped tile is removed, educe the index of all portions that have indices greater or equal
|
||||
## than the existing tile's index.
|
||||
## [br]
|
||||
## 1) Portion not mapped, exists in the tileset.
|
||||
## Map the portion to the existing tile and increase its times_used by one.
|
||||
## [br]
|
||||
## 2) Portion not mapped, does not exist in the tileset.
|
||||
## Add the portion as a tile in the tileset, set its index to be the tileset's tile size - 1.
|
||||
## [br]
|
||||
## 3) Portion mapped, tile did not change. Do nothing.
|
||||
## [br]
|
||||
## 4) Portion mapped, exists in the tileset.
|
||||
## The mapped tile still exists in the tileset.
|
||||
## Map the portion to the existing tile, increase its times_used by one,
|
||||
## and reduce the previously mapped tile's times_used by 1.
|
||||
## [br]
|
||||
## 5) Portion mapped, exists in the tileset.
|
||||
## The mapped tile does not exist in the tileset anymore.
|
||||
## Map the portion to the existing tile and increase its times_used by one.
|
||||
## Remove the previously mapped tile,
|
||||
## and reduce the index of all portions that have indices greater or equal
|
||||
## than the existing tile's index.
|
||||
## [br]
|
||||
## 6) Portion mapped, does not exist in the tileset.
|
||||
## The mapped tile still exists in the tileset.
|
||||
## Add the portion as a tile in the tileset, set its index to be the tileset's tile size - 1.
|
||||
## Reduce the previously mapped tile's times_used by 1.
|
||||
## [br]
|
||||
## 7) Portion mapped, does not exist in the tileset.
|
||||
## 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 current_tile := tileset.tiles[index]
|
||||
if image_portion.is_invisible():
|
||||
# Case 0: The portion is transparent.
|
||||
indices[i] = 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)
|
||||
if is_removed:
|
||||
# Re-index all indices that are after the deleted one.
|
||||
re_index_tiles_after_index(index)
|
||||
return
|
||||
var index_in_tileset := tileset.find_tile(image_portion)
|
||||
if index == 0: # If the portion is not mapped to a tile.
|
||||
if index_in_tileset > -1:
|
||||
# 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
|
||||
else:
|
||||
# Case 2: The portion is not mapped already,
|
||||
# and it does not exist in the tileset.
|
||||
tileset.add_tile(image_portion, TileSetPanel.tile_editing_mode)
|
||||
indices[i] = 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.
|
||||
# Do nothing and move on to the next portion.
|
||||
return
|
||||
var previous_tile_index_in_tileset := tileset.find_tile(current_tile.image)
|
||||
if index_in_tileset > -1: # If the portion exists in the tileset as a tile.
|
||||
if current_tile.times_used > 1:
|
||||
# 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
|
||||
tileset.unuse_tile_at_index(index)
|
||||
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
|
||||
tileset.remove_tile_at_index(index)
|
||||
# Re-index all indices that are after the deleted one.
|
||||
re_index_tiles_after_index(index)
|
||||
else: # If the portion does not exist in the tileset as a tile.
|
||||
if current_tile.times_used > 1:
|
||||
# Case 6: The portion is mapped and it does not
|
||||
# exist in the tileset as a tile,
|
||||
# and the currently mapped tile still exists in the tileset.
|
||||
tileset.unuse_tile_at_index(index)
|
||||
tileset.add_tile(image_portion, TileSetPanel.tile_editing_mode)
|
||||
indices[i] = tileset.tiles.size() - 1
|
||||
else:
|
||||
# Case 7: The portion is mapped and it does not
|
||||
# exist in the tileset as a tile,
|
||||
# and the currently mapped tile no longer exists in the tileset.
|
||||
tileset.replace_tile_at(image_portion, index)
|
||||
|
||||
|
||||
## Re-indexes all [member indices] that are larger or equal to [param index],
|
||||
## 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]
|
||||
if tmp_index >= index:
|
||||
indices[i] -= 1
|
||||
|
||||
|
||||
## Unused, should delete.
|
||||
func re_index_tiles() -> void:
|
||||
for i in indices.size():
|
||||
var x_coord := float(tileset.tile_size.x) * (i % indices_x)
|
||||
var y_coord := float(tileset.tile_size.y) * (i / indices_x)
|
||||
var rect := Rect2i(Vector2i(x_coord, y_coord), tileset.tile_size)
|
||||
var image_portion := image.get_region(rect)
|
||||
if image_portion.is_invisible():
|
||||
indices[i] = 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
|
||||
break
|
||||
|
||||
|
||||
func get_class_name() -> String:
|
||||
|
|
|
@ -11,11 +11,15 @@ var tiles: Array[Tile] = []
|
|||
class Tile:
|
||||
var image: Image
|
||||
var mode_added: TileSetPanel.TileEditingMode
|
||||
var times_used := 1
|
||||
|
||||
func _init(_image: Image, _mode_added: TileSetPanel.TileEditingMode) -> void:
|
||||
image = _image
|
||||
mode_added = _mode_added
|
||||
|
||||
func can_be_removed() -> bool:
|
||||
return mode_added != TileSetPanel.TileEditingMode.STACK and times_used <= 0
|
||||
|
||||
|
||||
func _init(_tile_size: Vector2i, _name := "") -> void:
|
||||
tile_size = _tile_size
|
||||
|
@ -39,6 +43,14 @@ func insert_tile(image: Image, position: int, edit_mode: TileSetPanel.TileEditin
|
|||
updated.emit()
|
||||
|
||||
|
||||
func unuse_tile_at_index(index: int) -> bool:
|
||||
tiles[index].times_used -= 1
|
||||
if tiles[index].can_be_removed():
|
||||
remove_tile_at_index(index)
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func remove_tile_at_index(index: int) -> void:
|
||||
tiles.remove_at(index)
|
||||
updated.emit()
|
||||
|
@ -47,3 +59,22 @@ func remove_tile_at_index(index: int) -> void:
|
|||
func replace_tile_at(new_tile: Image, index: int) -> void:
|
||||
tiles[index].image.copy_from(new_tile)
|
||||
updated.emit()
|
||||
|
||||
|
||||
func find_tile(image: Image) -> int:
|
||||
for i in tiles.size():
|
||||
var tile := tiles[i]
|
||||
if image.get_data() == tile.image.get_data():
|
||||
return i
|
||||
return -1
|
||||
|
||||
|
||||
## Unused, should delete.
|
||||
func remove_unused_tiles() -> bool:
|
||||
var tile_removed := false
|
||||
for i in range(tiles.size() - 1, 0, -1):
|
||||
var tile := tiles[i]
|
||||
if tile.can_be_removed():
|
||||
tile_removed = true
|
||||
remove_tile_at_index(i)
|
||||
return tile_removed
|
||||
|
|
Loading…
Reference in a new issue