diff --git a/src/Classes/Cels/CelTileMap.gd b/src/Classes/Cels/CelTileMap.gd index 562e8f12e..ac776c12b 100644 --- a/src/Classes/Cels/CelTileMap.gd +++ b/src/Classes/Cels/CelTileMap.gd @@ -33,6 +33,16 @@ class Tile: ## and then flipped vertically. var transpose := false + func _to_string() -> String: + var text := str(index) + if flip_h: + text += "H" + if flip_v: + text += "V" + if transpose: + text += "T" + return text + func serialize() -> Dictionary: return {"index": index, "flip_h": flip_h, "flip_v": flip_v, "transpose": transpose} @@ -52,6 +62,9 @@ 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 = index + indices[tile_position].flip_h = TileSetPanel.is_flipped_h + indices[tile_position].flip_v = TileSetPanel.is_flipped_v + indices[tile_position].transpose = TileSetPanel.is_transposed update_cel_portion(tile_position) Global.canvas.queue_redraw() @@ -215,11 +228,15 @@ 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].index - var current_tile := tileset.tiles[index] - if not tiles_equal(tile_position, image_portion, current_tile.image): - var tile_size := current_tile.image.get_size() - image.blit_rect(current_tile.image, Rect2i(Vector2i.ZERO, tile_size), coords) + var tile_data := indices[tile_position] + var index := tile_data.index + var current_tile := tileset.tiles[index].image + var transformed_tile := transform_tile( + current_tile, tile_data.flip_h, tile_data.flip_v, tile_data.transpose + ) + if not tiles_equal(tile_position, image_portion, transformed_tile): + var tile_size := transformed_tile.get_size() + image.blit_rect(transformed_tile, Rect2i(Vector2i.ZERO, tile_size), coords) func update_cel_portions() -> void: @@ -247,20 +264,33 @@ func get_tile_position(coords: Vector2i) -> int: func tiles_equal(portion_index: int, image_portion: Image, tile_image: Image) -> bool: var tile_data := indices[portion_index] - var final_image_portion := Image.new() - final_image_portion.copy_from(image_portion) - if tile_data.flip_h: - final_image_portion.flip_x() - if tile_data.flip_v: - final_image_portion.flip_y() - if tile_data.transpose: + var final_image_portion := transform_tile( + tile_image, tile_data.flip_h, tile_data.flip_v, tile_data.transpose + ) + return image_portion.get_data() == final_image_portion.get_data() + + +func transform_tile( + tile_image: Image, flip_h: bool, flip_v: bool, transpose: bool, reverse := false +) -> Image: + var transformed_tile := Image.new() + transformed_tile.copy_from(tile_image) + if flip_h: + transformed_tile.flip_x() + if flip_v: + transformed_tile.flip_y() + if transpose: var tmp_image := Image.new() - tmp_image.copy_from(final_image_portion) - tmp_image.rotate_90(COUNTERCLOCKWISE) - final_image_portion.blit_rect( + tmp_image.copy_from(transformed_tile) + if reverse: + tmp_image.rotate_90(CLOCKWISE) + else: + tmp_image.rotate_90(COUNTERCLOCKWISE) + transformed_tile.blit_rect( tmp_image, Rect2i(Vector2i.ZERO, tmp_image.get_size()), Vector2i.ZERO ) - return final_image_portion.get_data() == tile_image.get_data() + transformed_tile.flip_y() + return transformed_tile func re_index_all_tiles() -> void: @@ -316,7 +346,8 @@ func update_texture(undo := false) -> void: return for i in indices.size(): - var index := indices[i].index + var tile_data := indices[i] + var index := tile_data.index var coords := get_tile_coords(i) var rect := Rect2i(coords, tileset.tile_size) var image_portion := image.get_region(rect) @@ -329,14 +360,23 @@ func update_texture(undo := false) -> void: if editing_images.has(index): var editing_portion := editing_images[index][0] as int if i == editing_portion: - editing_images[index] = [i, image_portion] + var transformed_image := transform_tile( + image_portion, tile_data.flip_h, tile_data.flip_v, tile_data.transpose, true + ) + editing_images[index] = [i, transformed_image] var editing_image := editing_images[index][1] as Image - if not tiles_equal(i, image_portion, editing_image): + var transformed_editing_image := transform_tile( + editing_image, tile_data.flip_h, tile_data.flip_v, tile_data.transpose + ) + if not image_portion.get_data() == transformed_editing_image.get_data(): var tile_size := image_portion.get_size() - image.blit_rect(editing_image, Rect2i(Vector2i.ZERO, tile_size), coords) + image.blit_rect(transformed_editing_image, Rect2i(Vector2i.ZERO, tile_size), coords) else: if not tiles_equal(i, image_portion, current_tile.image): - editing_images[index] = [i, image_portion] + var transformed_image := transform_tile( + image_portion, tile_data.flip_h, tile_data.flip_v, tile_data.transpose, true + ) + editing_images[index] = [i, transformed_image] super.update_texture(undo) diff --git a/src/Tools/BaseDraw.gd b/src/Tools/BaseDraw.gd index 90c0ae9e1..64d3f973b 100644 --- a/src/Tools/BaseDraw.gd +++ b/src/Tools/BaseDraw.gd @@ -163,9 +163,17 @@ func update_config() -> void: func update_brush() -> void: $Brush/BrushSize.suffix = "px" # Assume we are using default brushes if is_placing_tiles(): - var tileset := (Global.current_project.get_current_cel() as CelTileMap).tileset + var tilemap_cel := Global.current_project.get_current_cel() as CelTileMap + var tileset := tilemap_cel.tileset var tile_index := clampi(TileSetPanel.selected_tile_index, 0, tileset.tiles.size() - 1) - _brush_image.copy_from(tileset.tiles[tile_index].image) + var tile_image := tileset.tiles[tile_index].image + tile_image = tilemap_cel.transform_tile( + tile_image, + TileSetPanel.is_flipped_h, + TileSetPanel.is_flipped_v, + TileSetPanel.is_transposed + ) + _brush_image.copy_from(tile_image) _brush_texture = ImageTexture.create_from_image(_brush_image) else: match _brush.type: diff --git a/src/UI/Canvas/TileModeIndices.gd b/src/UI/Canvas/TileModeIndices.gd index 2a130bd08..6f36d9b2e 100644 --- a/src/UI/Canvas/TileModeIndices.gd +++ b/src/UI/Canvas/TileModeIndices.gd @@ -13,5 +13,6 @@ 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].index) - draw_string(Themes.get_font(), pos, text, HORIZONTAL_ALIGNMENT_LEFT, -1, 10) + var tile_data := tilemap_cel.indices[i] + var text := tile_data.to_string() + draw_multiline_string(Themes.get_font(), pos, text, HORIZONTAL_ALIGNMENT_LEFT, -1, 10) diff --git a/src/UI/TilesPanel.gd b/src/UI/TilesPanel.gd index bbf909eb4..fabe67658 100644 --- a/src/UI/TilesPanel.gd +++ b/src/UI/TilesPanel.gd @@ -16,6 +16,18 @@ static var selected_tile_index := 0: set(value): selected_tile_index = value _call_update_brushes() +static var is_flipped_h := false: + set(value): + is_flipped_h = value + _call_update_brushes() +static var is_flipped_v := false: + set(value): + is_flipped_v = value + _call_update_brushes() +static var is_transposed := false: + set(value): + is_transposed = value + _call_update_brushes() var current_tileset: TileSetCustom var button_size := 36: set(value): @@ -35,7 +47,6 @@ var button_size := 36: func _ready() -> void: Tools.selected_tile_index_changed.connect(select_tile) Global.cel_switched.connect(_on_cel_switched) - #Global.project_switched.connect(_on_cel_switched) func _gui_input(event: InputEvent) -> void: @@ -151,3 +162,15 @@ func _on_auto_toggled(toggled_on: bool) -> void: func _on_stack_toggled(toggled_on: bool) -> void: if toggled_on: tile_editing_mode = TileEditingMode.STACK + + +func _on_flip_horizontal_button_toggled(toggled_on: bool) -> void: + is_flipped_h = toggled_on + + +func _on_flip_vertical_button_toggled(toggled_on: bool) -> void: + is_flipped_v = toggled_on + + +func _on_transpose_button_toggled(toggled_on: bool) -> void: + is_transposed = toggled_on diff --git a/src/UI/TilesPanel.tscn b/src/UI/TilesPanel.tscn index 6ffd270a1..5e1c4dcf9 100644 --- a/src/UI/TilesPanel.tscn +++ b/src/UI/TilesPanel.tscn @@ -20,6 +20,27 @@ layout_mode = 2 mouse_default_cursor_shape = 2 text = "Place tiles" +[node name="TransformButtonsContainer" type="HFlowContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="FlipHorizontalButton" type="Button" parent="VBoxContainer/TransformButtonsContainer"] +layout_mode = 2 +mouse_default_cursor_shape = 2 +toggle_mode = true +text = "H" + +[node name="FlipVerticalButton" type="Button" parent="VBoxContainer/TransformButtonsContainer"] +layout_mode = 2 +mouse_default_cursor_shape = 2 +toggle_mode = true +text = "V" + +[node name="TransposeButton" type="Button" parent="VBoxContainer/TransformButtonsContainer"] +layout_mode = 2 +mouse_default_cursor_shape = 2 +toggle_mode = true +text = "T" + [node name="ModeButtonsContainer" type="HFlowContainer" parent="VBoxContainer"] layout_mode = 2 @@ -53,6 +74,9 @@ size_flags_horizontal = 3 size_flags_vertical = 3 [connection signal="toggled" from="VBoxContainer/PlaceTiles" to="." method="_on_place_tiles_toggled"] +[connection signal="toggled" from="VBoxContainer/TransformButtonsContainer/FlipHorizontalButton" to="." method="_on_flip_horizontal_button_toggled"] +[connection signal="toggled" from="VBoxContainer/TransformButtonsContainer/FlipVerticalButton" to="." method="_on_flip_vertical_button_toggled"] +[connection signal="toggled" from="VBoxContainer/TransformButtonsContainer/TransposeButton" to="." method="_on_transpose_button_toggled"] [connection signal="toggled" from="VBoxContainer/ModeButtonsContainer/Manual" to="." method="_on_manual_toggled"] [connection signal="toggled" from="VBoxContainer/ModeButtonsContainer/Auto" to="." method="_on_auto_toggled"] [connection signal="toggled" from="VBoxContainer/ModeButtonsContainer/Stack" to="." method="_on_stack_toggled"]