1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-07 10:59:49 +00:00
Pixelorama/src/UI/TilesPanel.gd
2024-12-05 03:57:44 +02:00

208 lines
6.6 KiB
GDScript

class_name TileSetPanel
extends PanelContainer
enum TileEditingMode { MANUAL, AUTO, STACK }
const TRANSPARENT_CHECKER := preload("res://src/UI/Nodes/TransparentChecker.tscn")
const MIN_BUTTON_SIZE := 36
const MAX_BUTTON_SIZE := 144
## A matrix with every possible flip/transpose combination,
## sorted by what comes next when you rotate.
## Taken from Godot's rotation matrix found in:
## https://github.com/godotengine/godot/blob/master/editor/plugins/tiles/tile_map_layer_editor.cpp
const ROTATION_MATRIX: Array[bool] = [
0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1
]
static var placing_tiles := false:
set(value):
placing_tiles = value
_call_update_brushes()
static var tile_editing_mode := TileEditingMode.AUTO
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):
if button_size == value:
return
button_size = clampi(value, MIN_BUTTON_SIZE, MAX_BUTTON_SIZE)
update_minimum_size()
Global.config_cache.set_value("tileset_panel", "button_size", button_size)
for button: Control in tile_button_container.get_children():
button.custom_minimum_size = Vector2(button_size, button_size)
button.size = Vector2(button_size, button_size)
@onready var place_tiles: CheckBox = $VBoxContainer/PlaceTiles
@onready var transform_buttons_container: HFlowContainer = $VBoxContainer/TransformButtonsContainer
@onready var tile_button_container: HFlowContainer = %TileButtonContainer
func _ready() -> void:
Tools.selected_tile_index_changed.connect(select_tile)
Global.cel_switched.connect(_on_cel_switched)
for child: Button in transform_buttons_container.get_children():
Global.disable_button(child, true)
func _gui_input(event: InputEvent) -> void:
if Input.is_key_pressed(KEY_CTRL):
var zoom := 2 * int(event.is_action("zoom_in")) - 2 * int(event.is_action("zoom_out"))
button_size += zoom
if zoom != 0:
get_viewport().set_input_as_handled()
func set_tileset(tileset: TileSetCustom) -> void:
if tileset == current_tileset:
return
if is_instance_valid(current_tileset) and current_tileset.updated.is_connected(_update_tileset):
current_tileset.updated.disconnect(_update_tileset)
current_tileset = tileset
if (
is_instance_valid(current_tileset)
and not current_tileset.updated.is_connected(_update_tileset)
):
current_tileset.updated.connect(_update_tileset)
func _on_cel_switched() -> void:
if Global.current_project.get_current_cel() is not CelTileMap:
set_tileset(null)
_clear_tile_buttons()
return
var cel := Global.current_project.get_current_cel() as CelTileMap
set_tileset(cel.tileset)
_update_tileset(cel, -1)
func _update_tileset(cel: BaseCel, _replace_index: int) -> void:
_clear_tile_buttons()
if cel is not CelTileMap:
return
var tilemap_cel := cel as CelTileMap
var tileset := tilemap_cel.tileset
var button_group := ButtonGroup.new()
if selected_tile_index >= tileset.tiles.size():
selected_tile_index = 0
for i in tileset.tiles.size():
var tile := tileset.tiles[i]
var texture := ImageTexture.create_from_image(tile.image)
var button := _create_tile_button(texture, i, button_group)
if i == selected_tile_index:
button.set_pressed_no_signal(true)
tile_button_container.add_child(button)
func _create_tile_button(texture: Texture2D, index: int, button_group: ButtonGroup) -> Button:
var button := Button.new()
button.button_group = button_group
button.toggle_mode = true
button.custom_minimum_size = Vector2(button_size, button_size)
button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
var texture_rect := TextureRect.new()
texture_rect.texture = texture
texture_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
texture_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
texture_rect.set_anchor_and_offset(SIDE_LEFT, 0, 6)
texture_rect.set_anchor_and_offset(SIDE_RIGHT, 1, -6)
texture_rect.set_anchor_and_offset(SIDE_TOP, 0, 6)
texture_rect.set_anchor_and_offset(SIDE_BOTTOM, 1, -6)
texture_rect.grow_horizontal = Control.GROW_DIRECTION_BOTH
texture_rect.grow_vertical = Control.GROW_DIRECTION_BOTH
var transparent_checker := TRANSPARENT_CHECKER.instantiate() as ColorRect
transparent_checker.set_anchors_preset(Control.PRESET_FULL_RECT)
transparent_checker.show_behind_parent = true
texture_rect.add_child(transparent_checker)
button.add_child(texture_rect)
button.tooltip_text = str(index)
button.toggled.connect(_on_tile_button_toggled.bind(index))
return button
func select_tile(tile_index: int) -> void:
tile_button_container.get_child(tile_index).button_pressed = true
static func _call_update_brushes() -> void:
for slot in Tools._slots.values():
if slot.tool_node is BaseDrawTool:
slot.tool_node.update_brush()
func _on_tile_button_toggled(toggled_on: bool, index: int) -> void:
if toggled_on:
selected_tile_index = index
place_tiles.button_pressed = true
func _clear_tile_buttons() -> void:
for child in tile_button_container.get_children():
child.queue_free()
func _on_place_tiles_toggled(toggled_on: bool) -> void:
placing_tiles = toggled_on
for child: Button in transform_buttons_container.get_children():
Global.disable_button(child, not toggled_on)
func _on_manual_toggled(toggled_on: bool) -> void:
place_tiles.button_pressed = false
if toggled_on:
tile_editing_mode = TileEditingMode.MANUAL
func _on_auto_toggled(toggled_on: bool) -> void:
place_tiles.button_pressed = false
if toggled_on:
tile_editing_mode = TileEditingMode.AUTO
func _on_stack_toggled(toggled_on: bool) -> void:
place_tiles.button_pressed = false
if toggled_on:
tile_editing_mode = TileEditingMode.STACK
func _on_flip_horizontal_button_pressed() -> void:
is_flipped_h = not is_flipped_h
func _on_flip_vertical_button_pressed() -> void:
is_flipped_v = not is_flipped_v
func _on_rotate_pressed(clockwise: bool) -> void:
for i in ROTATION_MATRIX.size():
var final_i := i
if (
is_flipped_h == ROTATION_MATRIX[i * 3]
&& is_flipped_v == ROTATION_MATRIX[i * 3 + 1]
&& is_transposed == ROTATION_MATRIX[i * 3 + 2]
):
if clockwise:
@warning_ignore("integer_division")
final_i = i / 4 * 4 + posmod(i - 1, 4)
else:
@warning_ignore("integer_division")
final_i = i / 4 * 4 + (i + 1) % 4
is_flipped_h = ROTATION_MATRIX[final_i * 3]
is_flipped_v = ROTATION_MATRIX[final_i * 3 + 1]
is_transposed = ROTATION_MATRIX[final_i * 3 + 2]
break