mirror of
				https://github.com/JHDev2006/Super-Mario-Bros.-Remastered-Public.git
				synced 2025-10-25 08:50:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			940 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			GDScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			940 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			GDScript
		
	
	
		
			Executable File
		
	
	
	
	
| @tool
 | |
| extends Control
 | |
| 
 | |
| signal update_overlay
 | |
| signal force_show_terrains
 | |
| 
 | |
| # The maximum individual tiles the overlay will draw before shortcutting the display
 | |
| # To prevent editor lag when drawing large rectangles or filling large areas
 | |
| const MAX_CANVAS_RENDER_TILES = 1500
 | |
| const TERRAIN_PROPERTIES_SCENE := preload("res://addons/better-terrain/editor/TerrainProperties.tscn")
 | |
| const TERRAIN_ENTRY_SCENE := preload("res://addons/better-terrain/editor/TerrainEntry.tscn")
 | |
| const MIN_ZOOM_SETTING := "editor/better_terrain/min_zoom_amount"
 | |
| const MAX_ZOOM_SETTING := "editor/better_terrain/max_zoom_amount"
 | |
| 
 | |
| 
 | |
| # Buttons
 | |
| @onready var draw_button: Button = $VBox/Toolbar/Draw
 | |
| @onready var line_button: Button = $VBox/Toolbar/Line
 | |
| @onready var rectangle_button: Button = $VBox/Toolbar/Rectangle
 | |
| @onready var fill_button: Button = $VBox/Toolbar/Fill
 | |
| @onready var replace_button: Button = $VBox/Toolbar/Replace
 | |
| 
 | |
| @onready var paint_type: Button = $VBox/Toolbar/PaintType
 | |
| @onready var paint_terrain: Button = $VBox/Toolbar/PaintTerrain
 | |
| @onready var select_tiles: Button = $VBox/Toolbar/SelectTiles
 | |
| 
 | |
| @onready var paint_symmetry: Button = $VBox/Toolbar/PaintSymmetry
 | |
| @onready var symmetry_options: OptionButton = $VBox/Toolbar/SymmetryOptions
 | |
| 
 | |
| @onready var shuffle_random: Button = $VBox/Toolbar/ShuffleRandom
 | |
| @onready var zoom_slider_container: VBoxContainer = $VBox/Toolbar/ZoomContainer
 | |
| 
 | |
| @onready var source_selector: MenuBar = $VBox/Toolbar/Sources
 | |
| @onready var source_selector_popup: PopupMenu = $VBox/Toolbar/Sources/Sources
 | |
| 
 | |
| @onready var clean_button: Button = $VBox/Toolbar/Clean
 | |
| @onready var layer_up: Button = $VBox/Toolbar/LayerUp
 | |
| @onready var layer_down: Button = $VBox/Toolbar/LayerDown
 | |
| @onready var layer_highlight: Button = $VBox/Toolbar/LayerHighlight
 | |
| @onready var layer_grid: Button = $VBox/Toolbar/LayerGrid
 | |
| 
 | |
| @onready var grid_mode_button: Button = $VBox/HSplit/Terrains/LowerToolbar/GridMode
 | |
| @onready var quick_mode_button: Button = $VBox/HSplit/Terrains/LowerToolbar/QuickMode
 | |
| 
 | |
| @onready var edit_tool_buttons: HBoxContainer = $VBox/HSplit/Terrains/LowerToolbar/EditTools
 | |
| @onready var add_terrain_button: Button = $VBox/HSplit/Terrains/LowerToolbar/EditTools/AddTerrain
 | |
| @onready var edit_terrain_button: Button = $VBox/HSplit/Terrains/LowerToolbar/EditTools/EditTerrain
 | |
| @onready var pick_icon_button: Button = $VBox/HSplit/Terrains/LowerToolbar/EditTools/PickIcon
 | |
| @onready var move_up_button: Button = $VBox/HSplit/Terrains/LowerToolbar/EditTools/MoveUp
 | |
| @onready var move_down_button: Button = $VBox/HSplit/Terrains/LowerToolbar/EditTools/MoveDown
 | |
| @onready var remove_terrain_button: Button = $VBox/HSplit/Terrains/LowerToolbar/EditTools/RemoveTerrain
 | |
| 
 | |
| @onready var scroll_container: ScrollContainer = $VBox/HSplit/Terrains/Panel/ScrollContainer
 | |
| @onready var terrain_list: HFlowContainer = $VBox/HSplit/Terrains/Panel/ScrollContainer/TerrainList
 | |
| @onready var tile_view: Control = $VBox/HSplit/Panel/ScrollArea/TileView
 | |
| 
 | |
| 
 | |
| var selected_entry := -2
 | |
| 
 | |
| var tilemap : TileMapLayer
 | |
| var tileset : TileSet
 | |
| 
 | |
| var undo_manager : EditorUndoRedoManager
 | |
| var terrain_undo
 | |
| 
 | |
| var draw_overlay := false
 | |
| var initial_click : Vector2i
 | |
| var prev_position : Vector2i
 | |
| var current_position : Vector2i
 | |
| var tileset_dirty := false
 | |
| var zoom_slider : HSlider
 | |
| 
 | |
| enum PaintMode {
 | |
| 	NO_PAINT,
 | |
| 	PAINT,
 | |
| 	ERASE
 | |
| }
 | |
| 
 | |
| enum PaintAction {
 | |
| 	NO_ACTION,
 | |
| 	LINE,
 | |
| 	RECT
 | |
| }
 | |
| 
 | |
| enum SourceSelectors {
 | |
| 	ALL = 1000000,
 | |
| 	NONE = 1000001,
 | |
| }
 | |
| 
 | |
| var paint_mode := PaintMode.NO_PAINT
 | |
| 
 | |
| var paint_action := PaintAction.NO_ACTION
 | |
| 
 | |
| 
 | |
| # Called when the node enters the scene tree for the first time.
 | |
| func _ready() -> void:
 | |
| 	draw_button.icon = get_theme_icon("Edit", "EditorIcons")
 | |
| 	line_button.icon = get_theme_icon("Line", "EditorIcons")
 | |
| 	rectangle_button.icon = get_theme_icon("Rectangle", "EditorIcons")
 | |
| 	fill_button.icon = get_theme_icon("Bucket", "EditorIcons")
 | |
| 	select_tiles.icon = get_theme_icon("ToolSelect", "EditorIcons")
 | |
| 	add_terrain_button.icon = get_theme_icon("Add", "EditorIcons")
 | |
| 	edit_terrain_button.icon = get_theme_icon("Tools", "EditorIcons")
 | |
| 	pick_icon_button.icon = get_theme_icon("ColorPick", "EditorIcons")
 | |
| 	move_up_button.icon = get_theme_icon("ArrowUp", "EditorIcons")
 | |
| 	move_down_button.icon = get_theme_icon("ArrowDown", "EditorIcons")
 | |
| 	remove_terrain_button.icon = get_theme_icon("Remove", "EditorIcons")
 | |
| 	grid_mode_button.icon = get_theme_icon("FileThumbnail", "EditorIcons")
 | |
| 	quick_mode_button.icon = get_theme_icon("GuiVisibilityVisible", "EditorIcons")
 | |
| 	layer_up.icon = get_theme_icon("MoveUp", "EditorIcons")
 | |
| 	layer_down.icon = get_theme_icon("MoveDown", "EditorIcons")
 | |
| 	layer_highlight.icon = get_theme_icon("TileMapHighlightSelected", "EditorIcons")
 | |
| 	layer_grid.icon = get_theme_icon("Grid", "EditorIcons")
 | |
| 	
 | |
| 	select_tiles.button_group.pressed.connect(_on_bit_button_pressed)
 | |
| 	
 | |
| 	terrain_undo = load("res://addons/better-terrain/editor/TerrainUndo.gd").new()
 | |
| 	add_child(terrain_undo)
 | |
| 	tile_view.undo_manager = undo_manager
 | |
| 	tile_view.terrain_undo = terrain_undo
 | |
| 	
 | |
| 	tile_view.paste_occurred.connect(_on_paste_occurred)
 | |
| 	tile_view.change_zoom_level.connect(_on_change_zoom_level)
 | |
| 	tile_view.terrain_updated.connect(_on_terrain_updated)
 | |
| 	
 | |
| 	# Zoom slider is manipulated by settings, make it at runtime
 | |
| 	zoom_slider = HSlider.new()
 | |
| 	zoom_slider.custom_minimum_size = Vector2(100, 0)
 | |
| 	zoom_slider.value_changed.connect(tile_view._on_zoom_value_changed)
 | |
| 	zoom_slider_container.add_child(zoom_slider)
 | |
| 	
 | |
| 	# Init settings if needed
 | |
| 	if !ProjectSettings.has_setting(MIN_ZOOM_SETTING):
 | |
| 		ProjectSettings.set(MIN_ZOOM_SETTING, 1.0)
 | |
| 	ProjectSettings.add_property_info({
 | |
| 		"name": MIN_ZOOM_SETTING,
 | |
| 		"type": TYPE_FLOAT,
 | |
| 		"hint": PROPERTY_HINT_RANGE,
 | |
| 		"hint_string": "0.1,1.0,0.1"
 | |
| 	})
 | |
| 	ProjectSettings.set_initial_value(MIN_ZOOM_SETTING, 1.0)
 | |
| 	ProjectSettings.set_as_basic(MIN_ZOOM_SETTING, true)
 | |
| 	
 | |
| 	if !ProjectSettings.has_setting(MAX_ZOOM_SETTING):
 | |
| 		ProjectSettings.set(MAX_ZOOM_SETTING, 8.0)
 | |
| 	ProjectSettings.add_property_info({
 | |
| 		"name": MAX_ZOOM_SETTING,
 | |
| 		"type": TYPE_FLOAT,
 | |
| 		"hint": PROPERTY_HINT_RANGE,
 | |
| 		"hint_string": "2.0,32.0,1.0"
 | |
| 	})
 | |
| 	ProjectSettings.set_initial_value(MAX_ZOOM_SETTING, 8.0)
 | |
| 	ProjectSettings.set_as_basic(MAX_ZOOM_SETTING, true)
 | |
| 	ProjectSettings.set_order(MAX_ZOOM_SETTING, ProjectSettings.get_order(MIN_ZOOM_SETTING) + 1)
 | |
| 	
 | |
| 	ProjectSettings.settings_changed.connect(_on_adjust_settings)
 | |
| 	_on_adjust_settings()
 | |
| 	zoom_slider.value = 1.0
 | |
| 
 | |
| 
 | |
| func _process(delta):
 | |
| 	scroll_container.scroll_horizontal = 0
 | |
| 
 | |
| 
 | |
| func _on_adjust_settings():
 | |
| 	zoom_slider.min_value = ProjectSettings.get_setting(MIN_ZOOM_SETTING, 1.0)
 | |
| 	zoom_slider.max_value = ProjectSettings.get_setting(MAX_ZOOM_SETTING, 8.0)
 | |
| 	zoom_slider.step = (zoom_slider.max_value - zoom_slider.min_value) / 100.0
 | |
| 
 | |
| 
 | |
| func _get_fill_cells(target: Vector2i) -> Array:
 | |
| 	var pick := BetterTerrain.get_cell(tilemap, target)
 | |
| 	var bounds := tilemap.get_used_rect()
 | |
| 	var neighbors = BetterTerrain.data.cells_adjacent_for_fill(tileset)
 | |
| 	
 | |
| 	# No sets yet, so use a dictionary
 | |
| 	var checked := {}
 | |
| 	var pending := [target]
 | |
| 	var goal := []
 | |
| 	
 | |
| 	while !pending.is_empty():
 | |
| 		var p = pending.pop_front()
 | |
| 		if checked.has(p):
 | |
| 			continue
 | |
| 		checked[p] = true
 | |
| 		if !bounds.has_point(p) or BetterTerrain.get_cell(tilemap, p) != pick:
 | |
| 			continue
 | |
| 		
 | |
| 		goal.append(p)
 | |
| 		pending.append_array(BetterTerrain.data.neighboring_coords(tilemap, p, neighbors))
 | |
| 	
 | |
| 	return goal
 | |
| 
 | |
| 
 | |
| func tiles_about_to_change() -> void:
 | |
| 	if tileset and tileset.changed.is_connected(queue_tiles_changed):
 | |
| 		tileset.changed.disconnect(queue_tiles_changed)
 | |
| 
 | |
| 
 | |
| func tiles_changed() -> void:
 | |
| 	# ensure up to date
 | |
| 	BetterTerrain._update_terrain_data(tileset)
 | |
| 	
 | |
| 	# clear terrains
 | |
| 	for c in terrain_list.get_children():
 | |
| 		terrain_list.remove_child(c)
 | |
| 		c.queue_free()
 | |
| 	
 | |
| 	# load terrains from tileset
 | |
| 	var terrain_count := BetterTerrain.terrain_count(tileset)
 | |
| 	var item_count = terrain_count + 1
 | |
| 	for i in terrain_count:
 | |
| 		var terrain := BetterTerrain.get_terrain(tileset, i)
 | |
| 		if i >= terrain_list.get_child_count():
 | |
| 			add_terrain_entry(terrain, i)
 | |
| 	
 | |
| 	if item_count > terrain_list.get_child_count():
 | |
| 		var terrain := BetterTerrain.get_terrain(tileset, BetterTerrain.TileCategory.EMPTY)
 | |
| 		if terrain.valid:
 | |
| 			add_terrain_entry(terrain, item_count - 1)
 | |
| 	
 | |
| 	while item_count < terrain_list.get_child_count():
 | |
| 		var child = terrain_list.get_child(terrain_list.get_child_count() - 1)
 | |
| 		terrain_list.remove_child(child)
 | |
| 		child.free()
 | |
| 	
 | |
| 	source_selector_popup.clear()
 | |
| 	source_selector_popup.add_item("All", SourceSelectors.ALL)
 | |
| 	source_selector_popup.add_item("None", SourceSelectors.NONE)
 | |
| 	var source_count = tileset.get_source_count() if tileset else 0
 | |
| 	for s in source_count:
 | |
| 		var source_id = tileset.get_source_id(s)
 | |
| 		var source := tileset.get_source(source_id)
 | |
| 		if !(source is TileSetAtlasSource):
 | |
| 			continue
 | |
| 		
 | |
| 		var name := source.resource_name
 | |
| 		if name.is_empty():
 | |
| 			var texture := (source as TileSetAtlasSource).texture
 | |
| 			var texture_name := texture.resource_name if texture else ""
 | |
| 			if !texture_name.is_empty():
 | |
| 				name = texture_name
 | |
| 			else:
 | |
| 				var texture_path := texture.resource_path if texture else ""
 | |
| 				if !texture_path.is_empty():
 | |
| 					name = texture_path.get_file()
 | |
| 		
 | |
| 		if !name.is_empty():
 | |
| 			name += " "
 | |
| 		name += " (ID: %d)" % source_id
 | |
| 		
 | |
| 		source_selector_popup.add_check_item(name, source_id)
 | |
| 		source_selector_popup.set_item_checked(source_selector_popup.get_item_index(source_id), true)
 | |
| 	source_selector.visible = source_selector_popup.item_count > 3 # All, None and more than one source
 | |
| 	
 | |
| 	update_tile_view_paint()
 | |
| 	tile_view.refresh_tileset(tileset)
 | |
| 	
 | |
| 	if tileset and !tileset.changed.is_connected(queue_tiles_changed):
 | |
| 		tileset.changed.connect(queue_tiles_changed)
 | |
| 	
 | |
| 	clean_button.visible = BetterTerrain._has_invalid_peering_types(tileset)
 | |
| 	
 | |
| 	tileset_dirty = false
 | |
| 	_on_grid_mode_pressed()
 | |
| 	_on_quick_mode_pressed()
 | |
| 
 | |
| 
 | |
| func about_to_be_visible(visible: bool) -> void:
 | |
| 	if !visible:
 | |
| 		return
 | |
| 	
 | |
| 	if tileset != tilemap.tile_set:
 | |
| 		tiles_about_to_change()
 | |
| 		tileset = tilemap.tile_set
 | |
| 		tiles_changed()
 | |
| 	
 | |
| 	var settings := EditorInterface.get_editor_settings()
 | |
| 	layer_highlight.set_pressed_no_signal(settings.get_setting("editors/tiles_editor/highlight_selected_layer"))
 | |
| 	layer_grid.set_pressed_no_signal(settings.get_setting("editors/tiles_editor/display_grid"))
 | |
| 
 | |
| 
 | |
| func queue_tiles_changed() -> void:
 | |
| 	# Bring terrain data up to date with complex tileset changes
 | |
| 	if !tileset or tileset_dirty:
 | |
| 		return
 | |
| 	
 | |
| 	tileset_dirty = true
 | |
| 	tiles_changed.call_deferred()
 | |
| 
 | |
| 
 | |
| func _on_entry_select(index:int):
 | |
| 	selected_entry = index
 | |
| 	if selected_entry >= BetterTerrain.terrain_count(tileset):
 | |
| 		selected_entry = BetterTerrain.TileCategory.EMPTY
 | |
| 	for i in range(terrain_list.get_child_count()):
 | |
| 		if i != index:
 | |
| 			terrain_list.get_child(i).set_selected(false)
 | |
| 	update_tile_view_paint()
 | |
| 
 | |
| 
 | |
| func _on_clean_pressed() -> void:
 | |
| 	var confirmed := [false]
 | |
| 	var popup := ConfirmationDialog.new()
 | |
| 	popup.dialog_text = tr("Tile set changes have caused terrain to become invalid. Remove invalid terrain data?")
 | |
| 	popup.dialog_hide_on_ok = false
 | |
| 	popup.confirmed.connect(func():
 | |
| 		confirmed[0] = true
 | |
| 		popup.hide()
 | |
| 	)
 | |
| 	EditorInterface.popup_dialog_centered(popup)
 | |
| 	await popup.visibility_changed
 | |
| 	popup.queue_free()
 | |
| 	
 | |
| 	if confirmed[0]:
 | |
| 		undo_manager.create_action("Clean invalid terrain peering data", UndoRedo.MERGE_DISABLE, tileset)
 | |
| 		undo_manager.add_do_method(BetterTerrain, &"_clear_invalid_peering_types", tileset)
 | |
| 		undo_manager.add_do_method(self, &"tiles_changed")
 | |
| 		terrain_undo.create_peering_restore_point(undo_manager, tileset)
 | |
| 		undo_manager.add_undo_method(self, &"tiles_changed")
 | |
| 		undo_manager.commit_action()
 | |
| 
 | |
| 
 | |
| func _on_grid_mode_pressed() -> void:
 | |
| 	for c in terrain_list.get_children():
 | |
| 		c.grid_mode = grid_mode_button.button_pressed
 | |
| 		c.update_style()
 | |
| 
 | |
| 
 | |
| func _on_quick_mode_pressed() -> void:
 | |
| 	edit_tool_buttons.visible = !quick_mode_button.button_pressed
 | |
| 	for c in terrain_list.get_children():
 | |
| 		c.visible = !quick_mode_button.button_pressed or c.terrain.type in [BetterTerrain.TerrainType.MATCH_TILES, BetterTerrain.TerrainType.MATCH_VERTICES]
 | |
| 
 | |
| 
 | |
| func update_tile_view_paint() -> void:
 | |
| 	tile_view.paint = selected_entry
 | |
| 	tile_view.queue_redraw()
 | |
| 	
 | |
| 	var editable = tile_view.paint != BetterTerrain.TileCategory.EMPTY
 | |
| 	edit_terrain_button.disabled = !editable
 | |
| 	move_up_button.disabled = !editable or tile_view.paint == 0
 | |
| 	move_down_button.disabled = !editable or tile_view.paint == BetterTerrain.terrain_count(tileset) - 1
 | |
| 	remove_terrain_button.disabled = !editable
 | |
| 	pick_icon_button.disabled = !editable
 | |
| 
 | |
| 
 | |
| func _on_add_terrain_pressed() -> void:
 | |
| 	if !tileset:
 | |
| 		return
 | |
| 	
 | |
| 	var popup := TERRAIN_PROPERTIES_SCENE.instantiate()
 | |
| 	popup.set_category_data(BetterTerrain.get_terrain_categories(tileset))
 | |
| 	popup.terrain_name = "New terrain"
 | |
| 	popup.terrain_color = Color.from_hsv(randf(), 0.3 + 0.7 * randf(), 0.6 + 0.4 * randf())
 | |
| 	popup.terrain_icon = ""
 | |
| 	popup.terrain_type = 0
 | |
| 	EditorInterface.popup_dialog_centered(popup)
 | |
| 	await popup.visibility_changed
 | |
| 	if popup.accepted:
 | |
| 		undo_manager.create_action("Add terrain type", UndoRedo.MERGE_DISABLE, tileset)
 | |
| 		undo_manager.add_do_method(self, &"perform_add_terrain", popup.terrain_name, popup.terrain_color, popup.terrain_type, popup.terrain_categories, {path = popup.terrain_icon})
 | |
| 		undo_manager.add_undo_method(self, &"perform_remove_terrain", terrain_list.get_child_count() - 1)
 | |
| 		undo_manager.commit_action()
 | |
| 	popup.queue_free()
 | |
| 
 | |
| 
 | |
| func _on_edit_terrain_pressed() -> void:
 | |
| 	if !tileset:
 | |
| 		return
 | |
| 	
 | |
| 	if selected_entry < 0:
 | |
| 		return
 | |
| 	
 | |
| 	var t := BetterTerrain.get_terrain(tileset, selected_entry)
 | |
| 	var categories = BetterTerrain.get_terrain_categories(tileset)
 | |
| 	categories = categories.filter(func(x): return x.id != selected_entry)
 | |
| 	
 | |
| 	var popup := TERRAIN_PROPERTIES_SCENE.instantiate()
 | |
| 	popup.set_category_data(categories)
 | |
| 	
 | |
| 	t.icon = t.icon.duplicate()
 | |
| 	
 | |
| 	popup.terrain_name = t.name
 | |
| 	popup.terrain_type = t.type
 | |
| 	popup.terrain_color = t.color
 | |
| 	if t.has("icon") and t.icon.has("path"):
 | |
| 		popup.terrain_icon = t.icon.path
 | |
| 	popup.terrain_categories = t.categories
 | |
| 	EditorInterface.popup_dialog_centered(popup)
 | |
| 	await popup.visibility_changed
 | |
| 	if popup.accepted:
 | |
| 		undo_manager.create_action("Edit terrain details", UndoRedo.MERGE_DISABLE, tileset)
 | |
| 		undo_manager.add_do_method(self, &"perform_edit_terrain", selected_entry, popup.terrain_name, popup.terrain_color, popup.terrain_type, popup.terrain_categories, {path = popup.terrain_icon})
 | |
| 		undo_manager.add_undo_method(self, &"perform_edit_terrain", selected_entry, t.name, t.color, t.type, t.categories, t.icon)
 | |
| 		if t.type != popup.terrain_type:
 | |
| 			terrain_undo.create_terrain_type_restore_point(undo_manager, tileset)
 | |
| 			terrain_undo.create_peering_restore_point_specific(undo_manager, tileset, selected_entry)
 | |
| 		undo_manager.commit_action()
 | |
| 	popup.queue_free()
 | |
| 
 | |
| 
 | |
| func _on_pick_icon_pressed():
 | |
| 	if selected_entry < 0:
 | |
| 		return
 | |
| 	tile_view.pick_icon_terrain = selected_entry
 | |
| 
 | |
| 
 | |
| func _on_pick_icon_focus_exited():
 | |
| 	tile_view.pick_icon_terrain_cancel = true
 | |
| 	pick_icon_button.button_pressed = false
 | |
| 
 | |
| 
 | |
| func _on_move_pressed(down: bool) -> void:
 | |
| 	if !tileset:
 | |
| 		return
 | |
| 	
 | |
| 	if selected_entry < 0:
 | |
| 		return
 | |
| 	
 | |
| 	var index1 = selected_entry
 | |
| 	var index2 = index1 + (1 if down else -1)
 | |
| 	if index2 < 0 or index2 >= terrain_list.get_child_count():
 | |
| 		return
 | |
| 	
 | |
| 	undo_manager.create_action("Reorder terrains", UndoRedo.MERGE_DISABLE, tileset)
 | |
| 	undo_manager.add_do_method(self, &"perform_swap_terrain", index1, index2)
 | |
| 	undo_manager.add_undo_method(self, &"perform_swap_terrain", index1, index2)
 | |
| 	undo_manager.commit_action()
 | |
| 
 | |
| 
 | |
| func _on_remove_terrain_pressed() -> void:
 | |
| 	if !tileset:
 | |
| 		return
 | |
| 	
 | |
| 	if selected_entry < 0:
 | |
| 		return
 | |
| 	
 | |
| 	# store confirmation in array to pass by ref
 | |
| 	var t := BetterTerrain.get_terrain(tileset, selected_entry)
 | |
| 	var confirmed := [false]
 | |
| 	var popup := ConfirmationDialog.new()
 | |
| 	popup.dialog_text = tr("Are you sure you want to remove {0}?").format([t.name])
 | |
| 	popup.dialog_hide_on_ok = false
 | |
| 	popup.confirmed.connect(func():
 | |
| 		confirmed[0] = true
 | |
| 		popup.hide()
 | |
| 	)
 | |
| 	EditorInterface.popup_dialog_centered(popup)
 | |
| 	await popup.visibility_changed
 | |
| 	popup.queue_free()
 | |
| 	
 | |
| 	if confirmed[0]:
 | |
| 		undo_manager.create_action("Remove terrain type", UndoRedo.MERGE_DISABLE, tileset)
 | |
| 		undo_manager.add_do_method(self, &"perform_remove_terrain", selected_entry)
 | |
| 		undo_manager.add_undo_method(self, &"perform_add_terrain", t.name, t.color, t.type, t.categories, t.icon)
 | |
| 		for n in range(terrain_list.get_child_count() - 2, selected_entry, -1):
 | |
| 			undo_manager.add_undo_method(self, &"perform_swap_terrain", n, n - 1)
 | |
| 		if t.type == BetterTerrain.TerrainType.CATEGORY:
 | |
| 			terrain_undo.create_terrain_type_restore_point(undo_manager, tileset)
 | |
| 		terrain_undo.create_peering_restore_point_specific(undo_manager, tileset, selected_entry)
 | |
| 		undo_manager.commit_action()
 | |
| 
 | |
| 
 | |
| func add_terrain_entry(terrain:Dictionary, index:int = -1):
 | |
| 	if index < 0:
 | |
| 		index = terrain_list.get_child_count()
 | |
| 	
 | |
| 	var entry = TERRAIN_ENTRY_SCENE.instantiate()
 | |
| 	entry.tileset = tileset
 | |
| 	entry.terrain = terrain
 | |
| 	entry.grid_mode = grid_mode_button.button_pressed
 | |
| 	entry.select.connect(_on_entry_select)
 | |
| 	
 | |
| 	terrain_list.add_child(entry)
 | |
| 	terrain_list.move_child(entry, index)
 | |
| 
 | |
| 
 | |
| func remove_terrain_entry(index: int):
 | |
| 	terrain_list.get_child(index).free()
 | |
| 	for i in range(index, terrain_list.get_child_count()):
 | |
| 		var child = terrain_list.get_child(i)
 | |
| 		child.terrain = BetterTerrain.get_terrain(tileset, i)
 | |
| 		child.update()
 | |
| 
 | |
| 
 | |
| func perform_add_terrain(name: String, color: Color, type: int, categories: Array, icon:Dictionary = {}) -> void:
 | |
| 	if BetterTerrain.add_terrain(tileset, name, color, type, categories, icon):
 | |
| 		var index = BetterTerrain.terrain_count(tileset) - 1
 | |
| 		var terrain = BetterTerrain.get_terrain(tileset, index)
 | |
| 		add_terrain_entry(terrain, index)
 | |
| 
 | |
| 
 | |
| func perform_remove_terrain(index: int) -> void:
 | |
| 	if index >= BetterTerrain.terrain_count(tileset):
 | |
| 		return
 | |
| 	if BetterTerrain.remove_terrain(tileset, index):
 | |
| 		remove_terrain_entry(index)
 | |
| 		update_tile_view_paint()
 | |
| 
 | |
| 
 | |
| func perform_swap_terrain(index1: int, index2: int) -> void:
 | |
| 	var lower := min(index1, index2)
 | |
| 	var higher := max(index1, index2)
 | |
| 	if lower >= terrain_list.get_child_count() or higher >= terrain_list.get_child_count():
 | |
| 		return
 | |
| 	var item1 = terrain_list.get_child(lower)
 | |
| 	var item2 = terrain_list.get_child(higher)
 | |
| 	if BetterTerrain.swap_terrains(tileset, lower, higher):
 | |
| 		terrain_list.move_child(item1, higher)
 | |
| 		item1.terrain = BetterTerrain.get_terrain(tileset, higher)
 | |
| 		item1.update()
 | |
| 		item2.terrain = BetterTerrain.get_terrain(tileset, lower)
 | |
| 		item2.update()
 | |
| 		selected_entry = index2
 | |
| 		terrain_list.get_child(index2).set_selected(true)
 | |
| 		update_tile_view_paint()
 | |
| 
 | |
| 
 | |
| func perform_edit_terrain(index: int, name: String, color: Color, type: int, categories: Array, icon: Dictionary = {}) -> void:
 | |
| 	if index >= terrain_list.get_child_count():
 | |
| 		return
 | |
| 	var entry = terrain_list.get_child(index)
 | |
| 	# don't overwrite empty icon
 | |
| 	var valid_icon = icon
 | |
| 	if icon.has("path") and icon.path.is_empty():
 | |
| 		var terrain = BetterTerrain.get_terrain(tileset, index)
 | |
| 		valid_icon = terrain.icon
 | |
| 	if BetterTerrain.set_terrain(tileset, index, name, color, type, categories, valid_icon):
 | |
| 		entry.terrain = BetterTerrain.get_terrain(tileset, index)
 | |
| 		entry.update()
 | |
| 		tile_view.queue_redraw()
 | |
| 
 | |
| 
 | |
| func _on_shuffle_random_pressed():
 | |
| 	BetterTerrain.use_seed = !shuffle_random.button_pressed 
 | |
| 
 | |
| 
 | |
| func _on_bit_button_pressed(button: BaseButton) -> void:
 | |
| 	match select_tiles.button_group.get_pressed_button():
 | |
| 		select_tiles: tile_view.paint_mode = tile_view.PaintMode.SELECT
 | |
| 		paint_type: tile_view.paint_mode = tile_view.PaintMode.PAINT_TYPE
 | |
| 		paint_terrain: tile_view.paint_mode = tile_view.PaintMode.PAINT_PEERING
 | |
| 		paint_symmetry: tile_view.paint_mode = tile_view.PaintMode.PAINT_SYMMETRY
 | |
| 		_: tile_view.paint_mode = tile_view.PaintMode.NO_PAINT
 | |
| 	tile_view.queue_redraw()
 | |
| 	
 | |
| 	symmetry_options.visible = paint_symmetry.button_pressed
 | |
| 
 | |
| 
 | |
| func _on_symmetry_selected(index):
 | |
| 	tile_view.paint_symmetry = index
 | |
| 
 | |
| 
 | |
| func _on_paste_occurred():
 | |
| 	select_tiles.button_pressed = true
 | |
| 
 | |
| 
 | |
| func _on_change_zoom_level(value):
 | |
| 	zoom_slider.value = value
 | |
| 
 | |
| 
 | |
| func _on_terrain_updated(index):
 | |
| 	var entry = terrain_list.get_child(index)
 | |
| 	entry.terrain = BetterTerrain.get_terrain(tileset, index)
 | |
| 	entry.update()
 | |
| 
 | |
| 
 | |
| func canvas_tilemap_transform() -> Transform2D:
 | |
| 	var transform := tilemap.get_viewport_transform() * tilemap.global_transform
 | |
| 	
 | |
| 	# Handle subviewport
 | |
| 	var editor_viewport := EditorInterface.get_editor_viewport_2d()
 | |
| 	if tilemap.get_viewport() != editor_viewport:
 | |
| 		var container = tilemap.get_viewport().get_parent() as SubViewportContainer
 | |
| 		if container:
 | |
| 			transform = editor_viewport.global_canvas_transform * container.get_transform() * transform
 | |
| 	
 | |
| 	return transform
 | |
| 
 | |
| 
 | |
| func canvas_draw(overlay: Control) -> void:
 | |
| 	if !draw_overlay:
 | |
| 		return
 | |
| 	
 | |
| 	if selected_entry < 0:
 | |
| 		return
 | |
| 	
 | |
| 	var type = selected_entry
 | |
| 	var terrain := BetterTerrain.get_terrain(tileset, type)
 | |
| 	if !terrain.valid:
 | |
| 		return
 | |
| 	
 | |
| 	var tiles := []
 | |
| 	var transform := canvas_tilemap_transform()
 | |
| 	
 | |
| 	if paint_action == PaintAction.RECT and paint_mode != PaintMode.NO_PAINT:
 | |
| 		var area := Rect2i(initial_click, current_position - initial_click).abs()
 | |
| 
 | |
| 		# Shortcut fill for large areas
 | |
| 		if area.size.x > 1 and area.size.y > 1 and area.size.x * area.size.y > MAX_CANVAS_RENDER_TILES:
 | |
| 			var shortcut := PackedVector2Array([
 | |
| 				tilemap.map_to_local(area.position),
 | |
| 				tilemap.map_to_local(Vector2i(area.end.x, area.position.y)),
 | |
| 				tilemap.map_to_local(area.end),
 | |
| 				tilemap.map_to_local(Vector2i(area.position.x, area.end.y))
 | |
| 			])
 | |
| 			overlay.draw_colored_polygon(transform * shortcut, Color(terrain.color, 0.5))
 | |
| 			return
 | |
| 		
 | |
| 		for y in range(area.position.y, area.end.y + 1):
 | |
| 			for x in range(area.position.x, area.end.x + 1):
 | |
| 				tiles.append(Vector2i(x, y))
 | |
| 	elif paint_action == PaintAction.LINE and paint_mode != PaintMode.NO_PAINT:
 | |
| 		var cells := _get_tileset_line(initial_click, current_position, tileset)
 | |
| 		var shape = BetterTerrain.data.cell_polygon(tileset)
 | |
| 		for c in cells:
 | |
| 			var tile_transform := Transform2D(0.0, tilemap.tile_set.tile_size, 0.0, tilemap.map_to_local(c))
 | |
| 			overlay.draw_colored_polygon(transform * tile_transform * shape, Color(terrain.color, 0.5))
 | |
| 	elif fill_button.button_pressed:
 | |
| 		tiles = _get_fill_cells(current_position)
 | |
| 		if tiles.size() > MAX_CANVAS_RENDER_TILES:
 | |
| 			tiles.resize(MAX_CANVAS_RENDER_TILES)
 | |
| 	else:
 | |
| 		tiles.append(current_position)
 | |
| 	
 | |
| 	var shape = BetterTerrain.data.cell_polygon(tileset)
 | |
| 	for t in tiles:
 | |
| 		var tile_transform := Transform2D(0.0, tilemap.tile_set.tile_size, 0.0, tilemap.map_to_local(t))
 | |
| 		overlay.draw_colored_polygon(transform * tile_transform * shape, Color(terrain.color, 0.5))
 | |
| 
 | |
| 
 | |
| func canvas_input(event: InputEvent) -> bool:
 | |
| 	if selected_entry < 0:
 | |
| 		return false
 | |
| 	
 | |
| 	draw_overlay = true
 | |
| 	if event is InputEventMouseMotion:
 | |
| 		var tr := canvas_tilemap_transform()
 | |
| 		var pos := tr.affine_inverse() * Vector2(event.position)
 | |
| 		var event_position := tilemap.local_to_map(pos)
 | |
| 		prev_position = current_position
 | |
| 		if event_position == current_position:
 | |
| 			return false
 | |
| 		current_position = event_position
 | |
| 		update_overlay.emit()
 | |
| 	
 | |
| 	var replace_mode = replace_button.button_pressed
 | |
| 	
 | |
| 	var released : bool = event is InputEventMouseButton and !event.pressed
 | |
| 	if released:
 | |
| 		terrain_undo.finish_action()
 | |
| 		var type = selected_entry
 | |
| 		if paint_action == PaintAction.RECT and paint_mode != PaintMode.NO_PAINT:
 | |
| 			var area := Rect2i(initial_click, current_position - initial_click).abs()
 | |
| 			# Fill from initial_target to target
 | |
| 			undo_manager.create_action(tr("Draw terrain rectangle"), UndoRedo.MERGE_DISABLE, tilemap)
 | |
| 			for y in range(area.position.y, area.end.y + 1):
 | |
| 				for x in range(area.position.x, area.end.x + 1):
 | |
| 					var coord := Vector2i(x, y)
 | |
| 					if paint_mode == PaintMode.PAINT:
 | |
| 						if replace_mode:
 | |
| 							undo_manager.add_do_method(BetterTerrain, &"replace_cell", tilemap, coord, type)
 | |
| 						else:
 | |
| 							undo_manager.add_do_method(BetterTerrain, &"set_cell", tilemap, coord, type)
 | |
| 					else:
 | |
| 						undo_manager.add_do_method(tilemap, &"erase_cell", coord)
 | |
| 			
 | |
| 			undo_manager.add_do_method(BetterTerrain, &"update_terrain_area", tilemap, area)
 | |
| 			terrain_undo.create_tile_restore_point_area(undo_manager, tilemap, area)
 | |
| 			undo_manager.commit_action()
 | |
| 			update_overlay.emit()
 | |
| 		elif paint_action == PaintAction.LINE and paint_mode != PaintMode.NO_PAINT:
 | |
| 			undo_manager.create_action(tr("Draw terrain line"), UndoRedo.MERGE_DISABLE, tilemap)
 | |
| 			var cells := _get_tileset_line(initial_click, current_position, tileset)
 | |
| 			if paint_mode == PaintMode.PAINT:
 | |
| 				if replace_mode:
 | |
| 					undo_manager.add_do_method(BetterTerrain, &"replace_cells", tilemap, cells, type)
 | |
| 				else:
 | |
| 					undo_manager.add_do_method(BetterTerrain, &"set_cells", tilemap, cells, type)
 | |
| 			elif paint_mode == PaintMode.ERASE:
 | |
| 				for c in cells:
 | |
| 					undo_manager.add_do_method(tilemap, &"erase_cell", c)
 | |
| 			undo_manager.add_do_method(BetterTerrain, &"update_terrain_cells", tilemap, cells)
 | |
| 			terrain_undo.create_tile_restore_point(undo_manager, tilemap, cells)
 | |
| 			undo_manager.commit_action()
 | |
| 			update_overlay.emit()
 | |
| 		
 | |
| 		paint_mode = PaintMode.NO_PAINT
 | |
| 		return true
 | |
| 	
 | |
| 	var clicked : bool = event is InputEventMouseButton and event.pressed
 | |
| 	if clicked:
 | |
| 		paint_mode = PaintMode.NO_PAINT
 | |
| 		
 | |
| 		if (event.is_command_or_control_pressed() and !event.shift_pressed):
 | |
| 			var pick = BetterTerrain.get_cell(tilemap, current_position)
 | |
| 			if pick >= 0:
 | |
| 				terrain_list.get_children()[pick]._on_focus_entered()
 | |
| 				#_on_entry_select(pick)
 | |
| 			return true
 | |
| 		
 | |
| 		paint_action = PaintAction.NO_ACTION
 | |
| 		if rectangle_button.button_pressed:
 | |
| 			paint_action = PaintAction.RECT
 | |
| 		elif line_button.button_pressed:
 | |
| 			paint_action = PaintAction.LINE
 | |
| 		elif draw_button.button_pressed:
 | |
| 			if event.shift_pressed:
 | |
| 				paint_action = PaintAction.LINE
 | |
| 				if event.is_command_or_control_pressed():
 | |
| 					paint_action = PaintAction.RECT
 | |
| 		
 | |
| 		if event.button_index == MOUSE_BUTTON_LEFT:
 | |
| 			paint_mode = PaintMode.PAINT
 | |
| 		elif event.button_index == MOUSE_BUTTON_RIGHT:
 | |
| 			paint_mode = PaintMode.ERASE
 | |
| 		else:
 | |
| 			return false
 | |
| 	
 | |
| 	if (clicked or event is InputEventMouseMotion) and paint_mode != PaintMode.NO_PAINT:
 | |
| 		if clicked:
 | |
| 			initial_click = current_position
 | |
| 			terrain_undo.action_index += 1
 | |
| 			terrain_undo.action_count = 0
 | |
| 		var type = selected_entry
 | |
| 		
 | |
| 		if paint_action == PaintAction.LINE or paint_action == PaintAction.RECT:
 | |
| 			# if painting as line, execution happens on release. 
 | |
| 			# prevent other painting actions from running.
 | |
| 			pass
 | |
| 		elif draw_button.button_pressed:
 | |
| 			undo_manager.create_action(tr("Draw terrain") + str(terrain_undo.action_index), UndoRedo.MERGE_ALL, tilemap, true)
 | |
| 			var cells := _get_tileset_line(prev_position, current_position, tileset)
 | |
| 			if paint_mode == PaintMode.PAINT:
 | |
| 				if replace_mode:
 | |
| 					terrain_undo.add_do_method(undo_manager, BetterTerrain, &"replace_cells", [tilemap, cells, type])
 | |
| 				else:
 | |
| 					terrain_undo.add_do_method(undo_manager, BetterTerrain, &"set_cells", [tilemap, cells, type])
 | |
| 			elif paint_mode == PaintMode.ERASE:
 | |
| 				for c in cells:
 | |
| 					terrain_undo.add_do_method(undo_manager, tilemap, &"erase_cell", [c])
 | |
| 			terrain_undo.add_do_method(undo_manager, BetterTerrain, &"update_terrain_cells", [tilemap, cells])
 | |
| 			terrain_undo.create_tile_restore_point(undo_manager, tilemap, cells)
 | |
| 			undo_manager.commit_action()
 | |
| 			terrain_undo.action_count += 1
 | |
| 		elif fill_button.button_pressed:
 | |
| 			var cells := _get_fill_cells(current_position)
 | |
| 			undo_manager.create_action(tr("Fill terrain"), UndoRedo.MERGE_DISABLE, tilemap)
 | |
| 			if paint_mode == PaintMode.PAINT:
 | |
| 				if replace_mode:
 | |
| 					undo_manager.add_do_method(BetterTerrain, &"replace_cells", tilemap, cells, type)
 | |
| 				else:
 | |
| 					undo_manager.add_do_method(BetterTerrain, &"set_cells", tilemap, cells, type)
 | |
| 			elif paint_mode == PaintMode.ERASE:
 | |
| 				for c in cells:
 | |
| 					undo_manager.add_do_method(tilemap, &"erase_cell", c)
 | |
| 			undo_manager.add_do_method(BetterTerrain, &"update_terrain_cells", tilemap, cells)
 | |
| 			terrain_undo.create_tile_restore_point(undo_manager, tilemap, cells)
 | |
| 			undo_manager.commit_action()
 | |
| 		
 | |
| 		update_overlay.emit()
 | |
| 		return true
 | |
| 	
 | |
| 	return false
 | |
| 
 | |
| 
 | |
| func canvas_mouse_exit() -> void:
 | |
| 	draw_overlay = false
 | |
| 	update_overlay.emit()
 | |
| 
 | |
| 
 | |
| func _shortcut_input(event) -> void:
 | |
| 	if event is InputEventKey:
 | |
| 		if event.keycode == KEY_C and (event.is_command_or_control_pressed() and not event.echo):
 | |
| 			get_viewport().set_input_as_handled()
 | |
| 			tile_view.copy_selection()
 | |
| 		if event.keycode == KEY_V and (event.is_command_or_control_pressed() and not event.echo):
 | |
| 			get_viewport().set_input_as_handled()
 | |
| 			tile_view.paste_selection()
 | |
| 
 | |
| 
 | |
| ## bresenham alg ported from Geometry2D::bresenham_line()
 | |
| func _get_line(from:Vector2i, to:Vector2i) -> Array[Vector2i]:
 | |
| 	if from == to:
 | |
| 		return [to]
 | |
| 	
 | |
| 	var points:Array[Vector2i] = []
 | |
| 	var delta := (to - from).abs() * 2
 | |
| 	var step := (to - from).sign()
 | |
| 	var current := from
 | |
| 	
 | |
| 	if delta.x > delta.y:
 | |
| 		var err:int = delta.x / 2
 | |
| 		while current.x != to.x:
 | |
| 			points.push_back(current);
 | |
| 			err -= delta.y
 | |
| 			if err < 0:
 | |
| 				current.y += step.y
 | |
| 				err += delta.x
 | |
| 			current.x += step.x
 | |
| 	else:
 | |
| 		var err:int = delta.y / 2
 | |
| 		while current.y != to.y:
 | |
| 			points.push_back(current)
 | |
| 			err -= delta.x
 | |
| 			if err < 0:
 | |
| 				current.x += step.x
 | |
| 				err += delta.y
 | |
| 			current.y += step.y
 | |
| 	
 | |
| 	points.push_back(current);
 | |
| 	return points;
 | |
| 
 | |
| 
 | |
| ## half-offset bresenham alg ported from TileMapEditor::get_line
 | |
| func _get_tileset_line(from:Vector2i, to:Vector2i, tileset:TileSet) -> Array[Vector2i]:
 | |
| 	if tileset.tile_shape == TileSet.TILE_SHAPE_SQUARE:
 | |
| 		return _get_line(from, to)
 | |
| 	
 | |
| 	var points:Array[Vector2i] = []
 | |
| 	
 | |
| 	var transposed := tileset.get_tile_offset_axis() == TileSet.TILE_OFFSET_AXIS_VERTICAL
 | |
| 	if transposed:
 | |
| 		from = Vector2i(from.y, from.x)
 | |
| 		to = Vector2i(to.y, to.x)
 | |
| 
 | |
| 	var delta:Vector2i = to - from
 | |
| 	delta = Vector2i(2 * delta.x + abs(posmod(to.y, 2)) - abs(posmod(from.y, 2)), delta.y)
 | |
| 	var sign:Vector2i = delta.sign()
 | |
| 
 | |
| 	var current := from;
 | |
| 	points.push_back(Vector2i(current.y, current.x) if transposed else current)
 | |
| 
 | |
| 	var err := 0
 | |
| 	if abs(delta.y) < abs(delta.x):
 | |
| 		var err_step:Vector2i = 3 * delta.abs()
 | |
| 		while current != to:
 | |
| 			err += err_step.y
 | |
| 			if err > abs(delta.x):
 | |
| 				if sign.x == 0:
 | |
| 					current += Vector2i(sign.y, 0)
 | |
| 				else:
 | |
| 					current += Vector2i(sign.x if bool(current.y % 2) != (sign.x < 0) else 0, sign.y)
 | |
| 				err -= err_step.x
 | |
| 			else:
 | |
| 				current += Vector2i(sign.x, 0)
 | |
| 				err += err_step.y
 | |
| 			points.push_back(Vector2i(current.y, current.x) if transposed else current)
 | |
| 	else:
 | |
| 		var err_step:Vector2i = delta.abs()
 | |
| 		while current != to:
 | |
| 			err += err_step.x
 | |
| 			if err > 0:
 | |
| 				if sign.x == 0:
 | |
| 					current += Vector2i(0, sign.y)
 | |
| 				else:
 | |
| 					current += Vector2i(sign.x if bool(current.y % 2) != (sign.x < 0) else 0, sign.y)
 | |
| 				err -= err_step.y;
 | |
| 			else:
 | |
| 				if sign.x == 0:
 | |
| 					current += Vector2i(0, sign.y)
 | |
| 				else:
 | |
| 					current += Vector2i(-sign.x if bool(current.y % 2) != (sign.x > 0) else 0, sign.y)
 | |
| 				err += err_step.y
 | |
| 			points.push_back(Vector2i(current.y, current.x) if transposed else current)
 | |
| 	
 | |
| 	return points
 | |
| 
 | |
| 
 | |
| func _on_terrain_enable_id_pressed(id):
 | |
| 	if id in [SourceSelectors.ALL, SourceSelectors.NONE]:
 | |
| 		for i in source_selector_popup.item_count:
 | |
| 			if source_selector_popup.is_item_checkable(i):
 | |
| 				source_selector_popup.set_item_checked(i, id == SourceSelectors.ALL)
 | |
| 	else:
 | |
| 		var index = source_selector_popup.get_item_index(id)
 | |
| 		var checked = source_selector_popup.is_item_checked(index)
 | |
| 		source_selector_popup.set_item_checked(index, !checked)
 | |
| 	
 | |
| 	var disabled_sources : Array[int]
 | |
| 	for i in source_selector_popup.item_count:
 | |
| 		if source_selector_popup.is_item_checkable(i) and !source_selector_popup.is_item_checked(i):
 | |
| 			disabled_sources.append(source_selector_popup.get_item_id(i))
 | |
| 	tile_view.disabled_sources = disabled_sources
 | |
| 
 | |
| 
 | |
| func corresponding_tilemap_editor_button(similar: Button) -> Button:
 | |
| 	var editors = EditorInterface.get_base_control().find_children("*", "TileMapLayerEditor", true, false)
 | |
| 	var tile_map_layer_editor = editors[0]
 | |
| 	var buttons = tile_map_layer_editor.find_children("*", "Button", true, false)
 | |
| 	for button: Button in buttons:
 | |
| 		if button.icon == similar.icon:
 | |
| 			return button
 | |
| 	return null
 | |
| 
 | |
| 
 | |
| func _on_layer_up_or_down_pressed(button: Button) -> void:
 | |
| 	var matching_button = corresponding_tilemap_editor_button(button)
 | |
| 	if !matching_button:
 | |
| 		return
 | |
| 	
 | |
| 	# Major hack, to reduce flicker hide the tileset editor briefly
 | |
| 	var editors = EditorInterface.get_base_control().find_children("*", "TileSetEditor", true, false)
 | |
| 	var tile_set_editor = editors[0]
 | |
| 	
 | |
| 	matching_button.pressed.emit()
 | |
| 	tile_set_editor.modulate = Color.TRANSPARENT
 | |
| 	await get_tree().process_frame
 | |
| 	await get_tree().process_frame
 | |
| 	force_show_terrains.emit()
 | |
| 	tile_set_editor.modulate = Color.WHITE
 | |
| 
 | |
| 
 | |
| 
 | |
| func _on_layer_up_pressed() -> void:
 | |
| 	_on_layer_up_or_down_pressed(layer_up)
 | |
| 
 | |
| 
 | |
| func _on_layer_down_pressed() -> void:
 | |
| 	_on_layer_up_or_down_pressed(layer_down)
 | |
| 
 | |
| 
 | |
| func _on_layer_highlight_toggled(toggled: bool) -> void:
 | |
| 	var settings = EditorInterface.get_editor_settings()
 | |
| 	settings.set_setting("editors/tiles_editor/highlight_selected_layer", toggled)
 | |
| 	
 | |
| 	var highlight = corresponding_tilemap_editor_button(layer_highlight)
 | |
| 	if highlight:
 | |
| 		highlight.toggled.emit(toggled)
 | |
| 
 | |
| 
 | |
| func _on_layer_grid_toggled(toggled: bool) -> void:
 | |
| 	var settings = EditorInterface.get_editor_settings()
 | |
| 	settings.set_setting("editors/tiles_editor/display_grid", toggled)
 | |
| 	
 | |
| 	var grid = corresponding_tilemap_editor_button(layer_grid)
 | |
| 	if grid:
 | |
| 		grid.toggled.emit(toggled)
 | 
