diff --git a/src/Autoload/ExtensionsApi.gd b/src/Autoload/ExtensionsApi.gd index 1c6e381eb..b49f20050 100644 --- a/src/Autoload/ExtensionsApi.gd +++ b/src/Autoload/ExtensionsApi.gd @@ -26,7 +26,8 @@ var theme := ThemeAPI.new() ## Gives access to theme related functions. var tools := ToolAPI.new() ## Gives ability to add/remove tools. var selection := SelectionAPI.new() ## Gives access to pixelorama's selection system. var project := ProjectAPI.new() ## Gives access to project manipulation. -var exports := ExportAPI.new() ## Gives access to adding custom exporters. +var export := ExportAPI.new() ## Gives access to adding custom exporters. +var import := ImportAPI.new() ## Gives access to adding custom exporters. var signals := SignalsAPI.new() ## Gives access to the basic commonly used signals. ## This fail-safe below is designed to work ONLY if Pixelorama is launched in Godot Editor @@ -102,6 +103,18 @@ func get_api_version() -> int: return ProjectSettings.get_setting("application/config/ExtensionsAPI_Version") +## Returns the initial nodes of an extension named [param extension_name]. +## initial nodes are the nodes whose paths are in the [code]nodes[/code] key of an +## extension.json file. +func get_main_nodes(extension_name: StringName) -> Array[Node]: + var extensions_node = Global.control.get_node("Extensions") + var nodes: Array[Node] = [] + for child: Node in extensions_node.get_children(): + if child.is_in_group(extension_name): + nodes.append(child) + return nodes + + ## Gives Access to the general stuff. ## ## This part of Api provides stuff like commonly used Autoloads, App's version info etc @@ -656,6 +669,33 @@ class ExportAPI: ExtensionsApi.remove_action("add_exporter") +## Gives access to adding custom import options. +class ImportAPI: + ## [param import_scene] is a scene preload that will be instanced and added to "import options" + ## section of pixelorama's import dialogs and will appears whenever [param import_name] is + ## chosen from import menu. + ## [br] + ## [param import_scene] must have a a script containing:[br] + ## 1. An optional variable named [code]import_preview_dialog[/code] of type [ConfirmationDialog], + ## If present, it will automatically be assigned a reference to the relevant import dialog's + ## [code]ImportPreviewDialog[/code] class so that you can easily access variables and + ## methods of that class. (This variable is meant to be read-only)[br] + ## 2. The method [method initiate_import] which takes 2 arguments: [code]path[/code], + ## [code]image[/code], which are automatically passed to [method initiate_import] at + ## time of import. + func add_import_option(import_name: StringName, import_scene_preload: PackedScene): + var id = OpenSave.add_import_option(import_name, import_scene_preload) + ExtensionsApi.add_action("add_import_option") + return id + + ## Removes the import option with [param id] from Pixelorama. + func remove_import_option(id: int): + var import_name = OpenSave.custom_import_names.find_key(id) + OpenSave.custom_import_names.erase(import_name) + OpenSave.custom_importer_scenes.erase(id) + ExtensionsApi.remove_action("add_import_option") + + ## Gives access to the basic commonly used signals. ## ## Gives access to the basic commonly used signals. diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index 946e675e7..5b4daa86f 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -7,11 +7,15 @@ signal reference_image_imported var current_save_paths: PackedStringArray = [] ## Stores a filename of a backup file in user:// until user saves manually var backup_save_paths: PackedStringArray = [] -var preview_dialog_tscn := preload("res://src/UI/Dialogs/PreviewDialog.tscn") +var preview_dialog_tscn := preload("res://src/UI/Dialogs/ImportPreviewDialog.tscn") var preview_dialogs := [] ## Array of preview dialogs var last_dialog_option := 0 var autosave_timer: Timer +# custom importer related dictionaries (received from extensions) +var custom_import_names := {} ## Contains importer names as keys and ids as values +var custom_importer_scenes := {} ## Contains ids keys and import option preloads as values + func _ready() -> void: autosave_timer = Timer.new() @@ -72,8 +76,38 @@ func handle_loading_file(file: String) -> void: handle_loading_image(file, image) +func add_import_option(import_name: StringName, import_scene: PackedScene) -> int: + # Change format name if another one uses the same name + var existing_format_names = ( + ImportPreviewDialog.ImageImportOptions.keys() + custom_import_names.keys() + ) + for i in range(existing_format_names.size()): + var test_name = import_name + if i != 0: + test_name = str(test_name, "_", i) + if !existing_format_names.has(test_name): + import_name = test_name + break + + # Obtain a unique id + var id := ImportPreviewDialog.ImageImportOptions.size() + for i in custom_import_names.size(): + var format_id = id + i + if !custom_import_names.values().has(i): + id = format_id + # Add to custom_file_formats + custom_import_names.merge({import_name: id}) + custom_importer_scenes.merge({id: import_scene}) + return id + + func handle_loading_image(file: String, image: Image) -> void: - var preview_dialog := preview_dialog_tscn.instantiate() as PreviewDialog + var preview_dialog := preview_dialog_tscn.instantiate() as ImportPreviewDialog + # add custom importers to preview dialog + for import_name in custom_import_names.keys(): + var id = custom_import_names[import_name] + var new_import_option = custom_importer_scenes[id].instantiate() + preview_dialog.custom_importers[id] = new_import_option preview_dialogs.append(preview_dialog) preview_dialog.path = file preview_dialog.image = image @@ -630,17 +664,15 @@ func open_image_at_cel(image: Image, layer_index := 0, frame_index := 0) -> void project.undos += 1 project.undo_redo.create_action("Replaced Cel") - for i in project.frames.size(): - if i == frame_index: - image.convert(Image.FORMAT_RGBA8) - var cel := project.frames[i].cels[layer_index] - if not cel is PixelCel: - continue - var cel_image := Image.create(project_width, project_height, false, Image.FORMAT_RGBA8) - cel_image.blit_rect(image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO) - Global.undo_redo_compress_images( - {cel.image: cel_image.data}, {cel.image: cel.image.data}, project - ) + var cel := project.frames[frame_index].cels[layer_index] + if not cel is PixelCel: + return + image.convert(Image.FORMAT_RGBA8) + var cel_image := Image.create(project_width, project_height, false, Image.FORMAT_RGBA8) + cel_image.blit_rect(image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO) + Global.undo_redo_compress_images( + {cel.image: cel_image.data}, {cel.image: cel.image.data}, project + ) project.undo_redo.add_do_property(project, "selected_cels", []) project.undo_redo.add_do_method(project.change_cel.bind(frame_index, layer_index)) diff --git a/src/UI/Dialogs/PreviewDialog.gd b/src/UI/Dialogs/ImportPreviewDialog.gd similarity index 61% rename from src/UI/Dialogs/PreviewDialog.gd rename to src/UI/Dialogs/ImportPreviewDialog.gd index 76cf566d1..739896f30 100644 --- a/src/UI/Dialogs/PreviewDialog.gd +++ b/src/UI/Dialogs/ImportPreviewDialog.gd @@ -1,4 +1,4 @@ -class_name PreviewDialog +class_name ImportPreviewDialog extends ConfirmationDialog enum ImageImportOptions { @@ -28,55 +28,72 @@ var opened_once := false var is_main := false var hiding := false -@onready var texture_rect: TextureRect = $VBoxContainer/AspectRatioContainer/TextureRect -@onready var image_size_label: Label = $VBoxContainer/SizeContainer/ImageSizeLabel -@onready var frame_size_label: Label = $VBoxContainer/SizeContainer/FrameSizeLabel -@onready var smart_slice_checkbox := %SmartSliceButton as CheckBox -@onready var merge_threshold := %SmartOptions/Threshold as ValueSlider -@onready var merge_dist := %SmartOptions/MergeDist as ValueSlider -@onready -var spritesheet_manual_tab_options = $VBoxContainer/HBoxContainer/SpritesheetTabOptions/Manual -@onready var spritesheet_smart_tab_options := %SmartOptions as HBoxContainer -@onready var spritesheet_tab_options = $VBoxContainer/HBoxContainer/SpritesheetTabOptions -@onready var spritesheet_lay_opt = $VBoxContainer/HBoxContainer/SpritesheetLayerOptions -@onready var new_frame_options = $VBoxContainer/HBoxContainer/NewFrameOptions -@onready var replace_cel_options = $VBoxContainer/HBoxContainer/ReplaceCelOptions -@onready var new_layer_options = $VBoxContainer/HBoxContainer/NewLayerOptions -@onready var new_brush_options = $VBoxContainer/HBoxContainer/NewBrushOptions -@onready var new_brush_name = $VBoxContainer/HBoxContainer/NewBrushOptions/BrushName +## keeps track of which custom export to show when it's import option is selected +## Contains ids as keys and custion import option scenes as values +var custom_importers = {} -@onready var import_options: OptionButton = $VBoxContainer/HBoxContainer/ImportOption -@onready var apply_all: CheckBox = $VBoxContainer/ApplyAll +## A [TextureRect] containing the preview image +@onready var texture_rect: TextureRect = %TextureRect +## The [OptionButton] containing import options +@onready var import_option_button: OptionButton = %ImportOption +## A [CheckBox] for enabling apply all system. +@onready var apply_all: CheckBox = $VBoxContainer/VBoxContainer/ApplyAll + +## Label showing size of original image. +@onready var image_size_label: Label = $VBoxContainer/VBoxContainer/SizeContainer/ImageSizeLabel +## Label for showing size of image after import. +@onready var frame_size_label: Label = $VBoxContainer/VBoxContainer/SizeContainer/FrameSizeLabel +## Container for all types of advanced settings like [member spritesheet_options], +## [member new_brush_options] etc... +@onready var import_options: VBoxContainer = %ImportOptions + +# Below are some common settings grouped into categories and are made visible/invisible +# depending on what your import option requires. +## container of spritesheet related import options +@onready var spritesheet_options = %ImportOptions/SpritesheetOptions +## container of frame related import options +@onready var at_frame_option = %ImportOptions/AtFrame +## container of layer related import options +@onready var at_layer_option = %ImportOptions/AtLayer +## container of brush related import options +@onready var new_brush_options = %ImportOptions/NewBrushOptions -func _on_PreviewDialog_about_to_show() -> void: +func _on_ImportPreviewDialog_about_to_show() -> void: if opened_once: return opened_once = true # # order as in ImageImportOptions enum - import_options.add_item("New project") - import_options.add_item("Spritesheet (new project)") - import_options.add_item("Spritesheet (new layer)") - import_options.add_item("New frame") - import_options.add_item("Replace cel") - import_options.add_item("New layer") - import_options.add_item("New reference image") - import_options.add_item("New palette") - import_options.add_item("New brush") - import_options.add_item("New pattern") + import_option_button.add_item("New project") + import_option_button.add_item("Spritesheet (new project)") + import_option_button.add_item("Spritesheet (new layer)") + import_option_button.add_item("New frame") + import_option_button.add_item("Replace cel") + import_option_button.add_item("New layer") + import_option_button.add_item("New reference image") + import_option_button.add_item("New palette") + import_option_button.add_item("New brush") + import_option_button.add_item("New pattern") + # adding custom importers + for id in custom_importers.keys(): + var scene = custom_importers[id] + var import_name = OpenSave.custom_import_names.find_key(id) + scene.set("import_preview_dialog", self) + import_options.add_child(scene) + import_option_button.add_item(import_name, id) # Select the option that the preview dialog before it had selected - import_options.select(OpenSave.last_dialog_option) - import_options.item_selected.emit(OpenSave.last_dialog_option) + import_option_button.select(OpenSave.last_dialog_option) + import_option_button.item_selected.emit(import_option_button.selected) var img_texture := ImageTexture.create_from_image(image) texture_rect.texture = img_texture - spritesheet_manual_tab_options.get_node("HorizontalFrames").max_value = min( - spritesheet_manual_tab_options.get_node("HorizontalFrames").max_value, image.get_size().x - ) - spritesheet_manual_tab_options.get_node("VerticalFrames").max_value = min( - spritesheet_manual_tab_options.get_node("VerticalFrames").max_value, image.get_size().y - ) + # set max values of spritesheet options + var h_frames = spritesheet_options.find_child("HorizontalFrames") + var v_frames = spritesheet_options.find_child("VerticalFrames") + h_frames.max_value = min(h_frames.max_value, image.get_size().x) + v_frames.max_value = min(v_frames.max_value, image.get_size().y) + # set labels image_size_label.text = ( tr("Image Size") + ": " + str(image.get_size().x) + "×" + str(image.get_size().y) ) @@ -94,7 +111,7 @@ func _on_visibility_changed() -> void: return elif is_main: # if the main dialog is closed then close others too for child in Global.control.get_children(): - if child is PreviewDialog: + if child is ImportPreviewDialog: OpenSave.preview_dialogs.erase(child) child.queue_free() else: # dialogs being closed separately @@ -106,12 +123,12 @@ func _on_visibility_changed() -> void: Global.dialog_open(false) -func _on_PreviewDialog_confirmed() -> void: +func _on_ImportPreviewDialog_confirmed() -> void: if is_main: # if the main dialog is confirmed then confirm others too is_main = false synchronize() for child in Global.control.get_children(): - if child is PreviewDialog: + if child is ImportPreviewDialog: child.confirmed.emit() else: if current_import_option == ImageImportOptions.NEW_TAB: @@ -130,7 +147,7 @@ func _on_PreviewDialog_confirmed() -> void: ) elif current_import_option == ImageImportOptions.SPRITESHEET_LAYER: - var frame_index: int = spritesheet_lay_opt.get_node("AtFrameSpinbox").value - 1 + var frame_index: int = at_frame_option.get_node("AtFrameSpinbox").value - 1 if smart_slice: if !recycle_last_slice_result: obtain_sliced_data() @@ -153,16 +170,16 @@ func _on_PreviewDialog_confirmed() -> void: ) elif current_import_option == ImageImportOptions.NEW_FRAME: - var layer_index: int = new_frame_options.get_node("AtLayerOption").get_selected_id() + var layer_index: int = at_layer_option.get_node("AtLayerOption").get_selected_id() OpenSave.open_image_as_new_frame(image, layer_index) elif current_import_option == ImageImportOptions.REPLACE_CEL: - var layer_index: int = replace_cel_options.get_node("AtLayerOption").get_selected_id() - var frame_index: int = replace_cel_options.get_node("AtFrameSpinbox").value - 1 + var layer_index: int = at_layer_option.get_node("AtLayerOption").get_selected_id() + var frame_index: int = at_frame_option.get_node("AtFrameSpinbox").value - 1 OpenSave.open_image_at_cel(image, layer_index, frame_index) elif current_import_option == ImageImportOptions.NEW_LAYER: - var frame_index: int = new_layer_options.get_node("AtFrameSpinbox").value - 1 + var frame_index: int = at_frame_option.get_node("AtFrameSpinbox").value - 1 OpenSave.open_image_as_new_layer(image, path.get_basename().get_file(), frame_index) elif current_import_option == ImageImportOptions.NEW_REFERENCE_IMAGE: @@ -189,6 +206,12 @@ func _on_PreviewDialog_confirmed() -> void: var dir := DirAccess.open(path.get_base_dir()) dir.copy(path, Global.home_data_directory.path_join(location)) + else: + if current_import_option in custom_importers.keys(): + var importer = custom_importers[current_import_option] + if importer.has_method("initiate_import"): + importer.call("initiate_import", path, image) + func _on_ApplyAll_toggled(pressed: bool) -> void: is_main = pressed @@ -198,7 +221,7 @@ func _on_ApplyAll_toggled(pressed: bool) -> void: hide() visibility_changed.connect(_on_visibility_changed) for child in Global.control.get_children(): - if child != self and child is PreviewDialog: + if child != self and child is ImportPreviewDialog: child.hiding = pressed if pressed: child.hide() @@ -210,47 +233,45 @@ func _on_ApplyAll_toggled(pressed: bool) -> void: func synchronize() -> void: for child in Global.control.get_children(): - if child != self and child is PreviewDialog: - var dialog := child as PreviewDialog + if child != self and child is ImportPreviewDialog: + var dialog := child as ImportPreviewDialog #sync modes var id := current_import_option - dialog.import_options.select(id) - dialog.import_options.item_selected.emit(id) + dialog.import_option_button.select(id) + dialog.import_option_button.item_selected.emit(id) #sync properties (if any) if ( id == ImageImportOptions.SPRITESHEET_TAB or id == ImageImportOptions.SPRITESHEET_LAYER ): - dialog.spritesheet_manual_tab_options.get_node("HorizontalFrames").value = min( - spritesheet_manual_tab_options.get_node("HorizontalFrames").value, - image.get_size().x - ) - dialog.spritesheet_manual_tab_options.get_node("VerticalFrames").value = min( - spritesheet_manual_tab_options.get_node("VerticalFrames").value, - image.get_size().y - ) + var h_frames = spritesheet_options.find_child("HorizontalFrames") + var v_frames = spritesheet_options.find_child("VerticalFrames") + var d_h_frames = dialog.spritesheet_options.find_child("HorizontalFrames") + var d_v_frames = dialog.spritesheet_options.find_child("VerticalFrames") + d_h_frames.value = min(h_frames.value, image.get_size().x) + d_v_frames.value = min(v_frames.value, image.get_size().y) if id == ImageImportOptions.SPRITESHEET_LAYER: - dialog.spritesheet_lay_opt.get_node("AtFrameSpinbox").value = ( - spritesheet_lay_opt.get_node("AtFrameSpinbox").value + dialog.at_frame_option.get_node("AtFrameSpinbox").value = ( + at_frame_option.get_node("AtFrameSpinbox").value ) elif id == ImageImportOptions.NEW_FRAME: - dialog.new_frame_options.get_node("AtLayerOption").selected = ( - new_frame_options.get_node("AtLayerOption").selected + dialog.at_layer_option.get_node("AtLayerOption").selected = ( + at_layer_option.get_node("AtLayerOption").selected ) elif id == ImageImportOptions.REPLACE_CEL: - dialog.replace_cel_options.get_node("AtLayerOption").selected = ( - replace_cel_options.get_node("AtLayerOption").selected + dialog.at_layer_option.get_node("AtLayerOption").selected = ( + at_layer_option.get_node("AtLayerOption").selected ) - dialog.replace_cel_options.get_node("AtFrameSpinbox").value = ( - replace_cel_options.get_node("AtFrameSpinbox").value + dialog.at_frame_option.get_node("AtFrameSpinbox").value = ( + at_frame_option.get_node("AtFrameSpinbox").value ) elif id == ImageImportOptions.NEW_LAYER: - dialog.new_layer_options.get_node("AtFrameSpinbox").value = ( - new_layer_options.get_node("AtFrameSpinbox").value + dialog.at_frame_option.get_node("AtFrameSpinbox").value = ( + at_frame_option.get_node("AtFrameSpinbox").value ) elif id == ImageImportOptions.BRUSH: @@ -259,78 +280,93 @@ func synchronize() -> void: dialog.new_brush_options.get_node("BrushTypeOption").item_selected.emit(type) +func _hide_all_options(): + # reset some options + smart_slice = false + apply_all.disabled = false + spritesheet_options.get_node("SmartSliceToggle").button_pressed = false + at_frame_option.get_node("AtFrameSpinbox").allow_greater = false + setup_smart_slice(false) + # hide items + texture_rect.get_child(0).visible = false + texture_rect.get_child(1).visible = false + for child: Node in import_options.get_children(): + child.visible = false + + func _on_ImportOption_item_selected(id: ImageImportOptions) -> void: current_import_option = id OpenSave.last_dialog_option = current_import_option - smart_slice_checkbox.button_pressed = false - apply_all.disabled = false - smart_slice = false - smart_slice_checkbox.visible = false - spritesheet_tab_options.visible = false - spritesheet_lay_opt.visible = false - new_frame_options.visible = false - replace_cel_options.visible = false - new_layer_options.visible = false - new_brush_options.visible = false - texture_rect.get_child(0).visible = false - texture_rect.get_child(1).visible = false + _hide_all_options() + import_options.get_parent().visible = true if id == ImageImportOptions.SPRITESHEET_TAB: frame_size_label.visible = true - smart_slice_checkbox.visible = true - spritesheet_tab_options.visible = true + spritesheet_options.visible = true texture_rect.get_child(0).visible = true texture_rect.get_child(1).visible = true elif id == ImageImportOptions.SPRITESHEET_LAYER: frame_size_label.visible = true - smart_slice_checkbox.visible = true - spritesheet_lay_opt.visible = true - spritesheet_tab_options.visible = true + at_frame_option.visible = true + spritesheet_options.visible = true texture_rect.get_child(0).visible = true texture_rect.get_child(1).visible = true + at_frame_option.get_node("AtFrameSpinbox").allow_greater = true elif id == ImageImportOptions.NEW_FRAME: - new_frame_options.visible = true + at_layer_option.visible = true # Fill the at layer option button: - var at_layer_option: OptionButton = new_frame_options.get_node("AtLayerOption") - at_layer_option.clear() + var at_layer_option_button: OptionButton = at_layer_option.get_node("AtLayerOption") + at_layer_option_button.clear() var layers := Global.current_project.layers.duplicate() layers.reverse() var i := 0 for l in layers: if not l is PixelLayer: continue - at_layer_option.add_item(l.name, l.index) - at_layer_option.set_item_tooltip(i, l.get_layer_path()) + at_layer_option_button.add_item(l.name, l.index) + at_layer_option_button.set_item_tooltip(i, l.get_layer_path()) i += 1 - at_layer_option.selected = at_layer_option.get_item_count() - 1 + at_layer_option_button.selected = at_layer_option_button.get_item_count() - 1 + elif id == ImageImportOptions.REPLACE_CEL: - replace_cel_options.visible = true + at_frame_option.visible = true + at_layer_option.visible = true # Fill the at layer option button: - var at_layer_option: OptionButton = replace_cel_options.get_node("AtLayerOption") - at_layer_option.clear() + var at_layer_option_button: OptionButton = at_layer_option.get_node("AtLayerOption") + at_layer_option_button.clear() var layers := Global.current_project.layers.duplicate() layers.reverse() var i := 0 for l in layers: if not l is PixelLayer: continue - at_layer_option.add_item(l.name, l.index) - at_layer_option.set_item_tooltip(i, l.get_layer_path()) + at_layer_option_button.add_item(l.name, l.index) + at_layer_option_button.set_item_tooltip(i, l.get_layer_path()) i += 1 - at_layer_option.selected = at_layer_option.get_item_count() - 1 - var at_frame_spinbox: SpinBox = replace_cel_options.get_node("AtFrameSpinbox") + at_layer_option_button.selected = at_layer_option_button.get_item_count() - 1 + var at_frame_spinbox: SpinBox = at_frame_option.get_node("AtFrameSpinbox") at_frame_spinbox.max_value = Global.current_project.frames.size() elif id == ImageImportOptions.NEW_LAYER: - new_layer_options.visible = true - new_layer_options.get_node("AtFrameSpinbox").max_value = ( + at_frame_option.visible = true + at_frame_option.get_node("AtFrameSpinbox").max_value = ( Global.current_project.frames.size() ) elif id == ImageImportOptions.BRUSH: new_brush_options.visible = true + + else: + if id in ImageImportOptions.values(): + import_options.get_parent().visible = false + else: + if is_main: # Disable apply all (for import options added by extension) + apply_all.button_pressed = false + apply_all.disabled = true + if id in custom_importers.keys(): + custom_importers[id].visible = true _call_queue_redraw() @@ -339,8 +375,8 @@ func _on_smart_slice_toggled(button_pressed: bool) -> void: func setup_smart_slice(enabled: bool) -> void: - spritesheet_smart_tab_options.visible = enabled - spritesheet_manual_tab_options.visible = !enabled + spritesheet_options.get_node("Manual").visible = !enabled + spritesheet_options.get_node("Smart").visible = enabled if is_main: # Disable apply all (the algorithm is not fast enough for this) apply_all.button_pressed = false apply_all.disabled = enabled @@ -351,6 +387,8 @@ func setup_smart_slice(enabled: bool) -> void: func obtain_sliced_data() -> void: + var merge_threshold := spritesheet_options.find_child("Threshold") as ValueSlider + var merge_dist := spritesheet_options.find_child("MergeDist") as ValueSlider var unpak := RegionUnpacker.new(merge_threshold.value, merge_dist.value) sliced_rects = unpak.get_used_rects(texture_rect.texture.get_image()) @@ -396,9 +434,9 @@ func spritesheet_frame_value_changed() -> void: func _on_BrushTypeOption_item_selected(index: BrushTypes) -> void: brush_type = index - new_brush_name.visible = false + new_brush_options.get_node("BrushName").visible = false if brush_type == BrushTypes.RANDOM: - new_brush_name.visible = true + new_brush_options.get_node("BrushName").visible = true func add_brush() -> void: @@ -421,7 +459,7 @@ func add_brush() -> void: Brushes.add_project_brush(image, file_name) elif brush_type == BrushTypes.RANDOM: - var brush_name = new_brush_name.get_node("BrushNameLineEdit").text.to_lower() + var brush_name = new_brush_options.get_node("BrushName/BrushNameLineEdit").text.to_lower() if !brush_name.is_valid_filename(): return var dir := DirAccess.open(Global.home_data_directory.path_join("Brushes")) @@ -465,6 +503,7 @@ func _call_queue_redraw() -> void: var empty_array: Array[Rect2i] = [] $"%SmartSlice".show_preview(empty_array) $"%RowColumnLines".show_preview(1, 1) + await get_tree().process_frame if ( current_import_option == ImageImportOptions.SPRITESHEET_TAB or current_import_option == ImageImportOptions.SPRITESHEET_LAYER @@ -476,5 +515,5 @@ func _call_queue_redraw() -> void: $"%RowColumnLines".show_preview(spritesheet_vertical, spritesheet_horizontal) -func _on_size_changed() -> void: +func _on_preview_container_size_changed() -> void: _call_queue_redraw() diff --git a/src/UI/Dialogs/ImportPreviewDialog.tscn b/src/UI/Dialogs/ImportPreviewDialog.tscn new file mode 100644 index 000000000..97a2e0c14 --- /dev/null +++ b/src/UI/Dialogs/ImportPreviewDialog.tscn @@ -0,0 +1,255 @@ +[gd_scene load_steps=6 format=3 uid="uid://nba3nryom3ud"] + +[ext_resource type="Script" path="res://src/UI/Dialogs/ImportPreviewDialog.gd" id="1_r16hn"] +[ext_resource type="Script" path="res://src/UI/Dialogs/HelperScripts/RowColumnLines.gd" id="2_yokw4"] +[ext_resource type="Script" path="res://src/UI/Dialogs/HelperScripts/SmartSlicePreview.gd" id="3_aeccv"] +[ext_resource type="PackedScene" uid="uid://cii2hpylme60s" path="res://src/UI/Nodes/CollapsibleContainer.tscn" id="4_6ispq"] +[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="4_nmo33"] + +[node name="ImportPreviewDialog" type="ConfirmationDialog"] +canvas_item_default_texture_filter = 0 +position = Vector2i(0, 36) +size = Vector2i(316, 446) +script = ExtResource("1_r16hn") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 8.0 +offset_top = 8.0 +offset_right = -8.0 +offset_bottom = -49.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="AspectRatioContainer" type="AspectRatioContainer" parent="VBoxContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="TextureRect" type="TextureRect" parent="VBoxContainer/VBoxContainer/AspectRatioContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(300, 300) +layout_mode = 2 +expand_mode = 1 +stretch_mode = 5 + +[node name="RowColumnLines" type="Control" parent="VBoxContainer/VBoxContainer/AspectRatioContainer/TextureRect"] +unique_name_in_owner = true +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("2_yokw4") + +[node name="SmartSlice" type="Control" parent="VBoxContainer/VBoxContainer/AspectRatioContainer/TextureRect"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("3_aeccv") + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer/VBoxContainer"] +layout_mode = 2 + +[node name="ApplyAll" type="CheckBox" parent="VBoxContainer/VBoxContainer"] +visible = false +layout_mode = 2 +text = "Apply to all" + +[node name="SizeContainer" type="HBoxContainer" parent="VBoxContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/separation = 32 + +[node name="ImageSizeLabel" type="Label" parent="VBoxContainer/VBoxContainer/SizeContainer"] +layout_mode = 2 +text = "Image Size: 64×64" + +[node name="FrameSizeLabel" type="Label" parent="VBoxContainer/VBoxContainer/SizeContainer"] +visible = false +layout_mode = 2 +text = "Frame size: 64×64" + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 0 +text = "Import as:" + +[node name="ImportOption" type="OptionButton" parent="VBoxContainer/VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 0 +mouse_default_cursor_shape = 2 + +[node name="ImportOptionsContainer" parent="VBoxContainer" instance=ExtResource("4_6ispq")] +layout_mode = 2 +text = "Import Options" + +[node name="ImportOptions" type="VBoxContainer" parent="VBoxContainer/ImportOptionsContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 + +[node name="SpritesheetOptions" type="VBoxContainer" parent="VBoxContainer/ImportOptionsContainer/ImportOptions"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Manual" type="HBoxContainer" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Manual"] +layout_mode = 2 +text = "Horizontal frames:" + +[node name="HorizontalFrames" type="SpinBox" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Manual"] +layout_mode = 2 +mouse_default_cursor_shape = 2 +min_value = 1.0 +value = 1.0 + +[node name="Label2" type="Label" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Manual"] +layout_mode = 2 +text = "Vertical frames:" + +[node name="VerticalFrames" type="SpinBox" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Manual"] +layout_mode = 2 +mouse_default_cursor_shape = 2 +min_value = 1.0 +value = 1.0 + +[node name="Smart" type="HBoxContainer" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions"] +visible = false +layout_mode = 2 + +[node name="Threshold" type="TextureProgressBar" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Smart"] +custom_minimum_size = Vector2(0, 30) +layout_mode = 2 +size_flags_horizontal = 3 +tooltip_text = "Images that have any one side smaller than this value will cross the threshold" +focus_mode = 2 +theme_type_variation = &"ValueSlider" +value = 10.0 +allow_greater = true +nine_patch_stretch = true +stretch_margin_left = 3 +stretch_margin_top = 3 +stretch_margin_right = 3 +stretch_margin_bottom = 3 +script = ExtResource("4_nmo33") +prefix = "Threshold:" +suffix = "px" + +[node name="MergeDist" type="TextureProgressBar" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Smart"] +custom_minimum_size = Vector2(0, 30) +layout_mode = 2 +size_flags_horizontal = 3 +tooltip_text = "Images which crossed the threshold will get merged into a larger image, if they are within this distance" +focus_mode = 2 +theme_type_variation = &"ValueSlider" +value = 3.0 +nine_patch_stretch = true +stretch_margin_left = 3 +stretch_margin_top = 3 +stretch_margin_right = 3 +stretch_margin_bottom = 3 +script = ExtResource("4_nmo33") +prefix = "Merge distance:" +suffix = "px" + +[node name="Slice" type="Button" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Smart"] +layout_mode = 2 +mouse_default_cursor_shape = 2 +text = "Refresh" + +[node name="SmartSliceToggle" type="CheckBox" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions"] +unique_name_in_owner = true +layout_mode = 2 +mouse_default_cursor_shape = 2 +text = "Smart Slice" + +[node name="AtFrame" type="HBoxContainer" parent="VBoxContainer/ImportOptionsContainer/ImportOptions"] +visible = false +layout_mode = 2 + +[node name="Label3" type="Label" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/AtFrame"] +layout_mode = 2 +text = "At frame:" + +[node name="AtFrameSpinbox" type="SpinBox" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/AtFrame"] +layout_mode = 2 +size_flags_vertical = 0 +min_value = 1.0 +value = 1.0 + +[node name="AtLayer" type="GridContainer" parent="VBoxContainer/ImportOptionsContainer/ImportOptions"] +visible = false +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/AtLayer"] +layout_mode = 2 +text = "At layer:" + +[node name="AtLayerOption" type="OptionButton" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/AtLayer"] +layout_mode = 2 +mouse_default_cursor_shape = 2 + +[node name="NewBrushOptions" type="HBoxContainer" parent="VBoxContainer/ImportOptionsContainer/ImportOptions"] +visible = false +layout_mode = 2 + +[node name="Type" type="HBoxContainer" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/NewBrushOptions"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/NewBrushOptions/Type"] +layout_mode = 2 +text = "Brush type:" + +[node name="BrushTypeOption" type="OptionButton" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/NewBrushOptions/Type"] +layout_mode = 2 +mouse_default_cursor_shape = 2 +item_count = 3 +selected = 0 +popup/item_0/text = "File brush" +popup/item_0/id = 0 +popup/item_1/text = "Project brush" +popup/item_1/id = 1 +popup/item_2/text = "Random brush" +popup/item_2/id = 2 + +[node name="BrushName" type="HBoxContainer" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/NewBrushOptions"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/NewBrushOptions/BrushName"] +layout_mode = 2 +text = "Brush name:" + +[node name="BrushNameLineEdit" type="LineEdit" parent="VBoxContainer/ImportOptionsContainer/ImportOptions/NewBrushOptions/BrushName"] +layout_mode = 2 + +[connection signal="about_to_popup" from="." to="." method="_on_ImportPreviewDialog_about_to_show"] +[connection signal="confirmed" from="." to="." method="_on_ImportPreviewDialog_confirmed"] +[connection signal="visibility_changed" from="." to="." method="_on_visibility_changed"] +[connection signal="resized" from="VBoxContainer/VBoxContainer" to="." method="_on_preview_container_size_changed"] +[connection signal="toggled" from="VBoxContainer/VBoxContainer/ApplyAll" to="." method="_on_ApplyAll_toggled"] +[connection signal="item_selected" from="VBoxContainer/VBoxContainer/HBoxContainer/ImportOption" to="." method="_on_ImportOption_item_selected"] +[connection signal="value_changed" from="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Manual/HorizontalFrames" to="." method="_on_HorizontalFrames_value_changed"] +[connection signal="value_changed" from="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Manual/VerticalFrames" to="." method="_on_VerticalFrames_value_changed"] +[connection signal="value_changed" from="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Smart/Threshold" to="." method="_on_threshold_value_changed"] +[connection signal="value_changed" from="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Smart/MergeDist" to="." method="_on_merge_dist_value_changed"] +[connection signal="pressed" from="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/Smart/Slice" to="." method="_on_slice_pressed"] +[connection signal="toggled" from="VBoxContainer/ImportOptionsContainer/ImportOptions/SpritesheetOptions/SmartSliceToggle" to="." method="_on_smart_slice_toggled"] +[connection signal="item_selected" from="VBoxContainer/ImportOptionsContainer/ImportOptions/NewBrushOptions/Type/BrushTypeOption" to="." method="_on_BrushTypeOption_item_selected"] diff --git a/src/UI/Dialogs/PreviewDialog.tscn b/src/UI/Dialogs/PreviewDialog.tscn deleted file mode 100644 index 7ada23345..000000000 --- a/src/UI/Dialogs/PreviewDialog.tscn +++ /dev/null @@ -1,266 +0,0 @@ -[gd_scene load_steps=5 format=3 uid="uid://nba3nryom3ud"] - -[ext_resource type="Script" path="res://src/UI/Dialogs/PreviewDialog.gd" id="1"] -[ext_resource type="Script" path="res://src/UI/Dialogs/HelperScripts/RowColumnLines.gd" id="2_fni44"] -[ext_resource type="Script" path="res://src/UI/Dialogs/HelperScripts/SmartSlicePreview.gd" id="3_lsglt"] -[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="4_e0gk1"] - -[node name="PreviewDialog" type="ConfirmationDialog"] -canvas_item_default_texture_filter = 0 -size = Vector2i(316, 417) -script = ExtResource("1") - -[node name="VBoxContainer" type="VBoxContainer" parent="."] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 8.0 -offset_top = 8.0 -offset_right = -8.0 -offset_bottom = -49.0 - -[node name="AspectRatioContainer" type="AspectRatioContainer" parent="VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="TextureRect" type="TextureRect" parent="VBoxContainer/AspectRatioContainer"] -custom_minimum_size = Vector2(300, 300) -layout_mode = 2 -expand_mode = 1 -stretch_mode = 5 - -[node name="RowColumnLines" type="Control" parent="VBoxContainer/AspectRatioContainer/TextureRect"] -unique_name_in_owner = true -anchors_preset = 0 -offset_right = 40.0 -offset_bottom = 40.0 -script = ExtResource("2_fni44") - -[node name="SmartSlice" type="Control" parent="VBoxContainer/AspectRatioContainer/TextureRect"] -unique_name_in_owner = true -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("3_lsglt") - -[node name="ApplyAll" type="CheckBox" parent="VBoxContainer"] -visible = false -layout_mode = 2 -text = "Apply to all" - -[node name="SizeContainer" type="HBoxContainer" parent="VBoxContainer"] -layout_mode = 2 -theme_override_constants/separation = 32 - -[node name="ImageSizeLabel" type="Label" parent="VBoxContainer/SizeContainer"] -layout_mode = 2 -text = "Image Size: 64×64" - -[node name="FrameSizeLabel" type="Label" parent="VBoxContainer/SizeContainer"] -visible = false -layout_mode = 2 -text = "Frame size: 64×64" - -[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] -layout_mode = 2 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer"] -layout_mode = 2 -size_flags_vertical = 0 -text = "Import as:" - -[node name="ImportOption" type="OptionButton" parent="VBoxContainer/HBoxContainer"] -layout_mode = 2 -size_flags_vertical = 0 -mouse_default_cursor_shape = 2 - -[node name="SpritesheetTabOptions" type="GridContainer" parent="VBoxContainer/HBoxContainer"] -visible = false -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="Manual" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions"] -layout_mode = 2 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions/Manual"] -layout_mode = 2 -text = "Horizontal frames:" - -[node name="HorizontalFrames" type="SpinBox" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions/Manual"] -layout_mode = 2 -mouse_default_cursor_shape = 2 -min_value = 1.0 -value = 1.0 - -[node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions/Manual"] -layout_mode = 2 -text = "Vertical frames:" - -[node name="VerticalFrames" type="SpinBox" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions/Manual"] -layout_mode = 2 -mouse_default_cursor_shape = 2 -min_value = 1.0 -value = 1.0 - -[node name="SmartOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions"] -unique_name_in_owner = true -visible = false -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="Threshold" type="TextureProgressBar" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions/SmartOptions"] -layout_mode = 2 -size_flags_horizontal = 3 -tooltip_text = "Images that have any one side smaller than this value will cross the threshold" -focus_mode = 2 -theme_type_variation = &"ValueSlider" -value = 10.0 -allow_greater = true -nine_patch_stretch = true -stretch_margin_left = 3 -stretch_margin_top = 3 -stretch_margin_right = 3 -stretch_margin_bottom = 3 -script = ExtResource("4_e0gk1") -prefix = "Threshold:" -suffix = "px" - -[node name="MergeDist" type="TextureProgressBar" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions/SmartOptions"] -layout_mode = 2 -size_flags_horizontal = 3 -tooltip_text = "Images which crossed the threshold will get merged into a larger image, if they are within this distance" -focus_mode = 2 -theme_type_variation = &"ValueSlider" -value = 3.0 -nine_patch_stretch = true -stretch_margin_left = 3 -stretch_margin_top = 3 -stretch_margin_right = 3 -stretch_margin_bottom = 3 -script = ExtResource("4_e0gk1") -prefix = "Merge distance:" -suffix = "px" - -[node name="Slice" type="Button" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions/SmartOptions"] -layout_mode = 2 -mouse_default_cursor_shape = 2 -text = "Refresh" - -[node name="SmartSliceButton" type="CheckBox" parent="VBoxContainer/HBoxContainer/SpritesheetTabOptions"] -unique_name_in_owner = true -layout_mode = 2 -mouse_default_cursor_shape = 2 -text = "Smart Slice" - -[node name="SpritesheetLayerOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] -visible = false -layout_mode = 2 - -[node name="Label3" type="Label" parent="VBoxContainer/HBoxContainer/SpritesheetLayerOptions"] -layout_mode = 2 -size_flags_vertical = 0 -text = "Start frame:" - -[node name="AtFrameSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/SpritesheetLayerOptions"] -layout_mode = 2 -size_flags_vertical = 0 -min_value = 1.0 -value = 1.0 - -[node name="NewFrameOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] -visible = false -layout_mode = 2 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/NewFrameOptions"] -layout_mode = 2 -text = "At layer:" - -[node name="AtLayerOption" type="OptionButton" parent="VBoxContainer/HBoxContainer/NewFrameOptions"] -layout_mode = 2 -mouse_default_cursor_shape = 2 - -[node name="ReplaceCelOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] -visible = false -layout_mode = 2 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] -layout_mode = 2 -text = "At layer:" - -[node name="AtLayerOption" type="OptionButton" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] -layout_mode = 2 -mouse_default_cursor_shape = 2 - -[node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] -layout_mode = 2 -text = "At frame:" - -[node name="AtFrameSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/ReplaceCelOptions"] -layout_mode = 2 -mouse_default_cursor_shape = 2 -min_value = 1.0 -max_value = 1.0 -value = 1.0 - -[node name="NewLayerOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] -visible = false -layout_mode = 2 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/NewLayerOptions"] -layout_mode = 2 -text = "At frame:" - -[node name="AtFrameSpinbox" type="SpinBox" parent="VBoxContainer/HBoxContainer/NewLayerOptions"] -layout_mode = 2 -mouse_default_cursor_shape = 2 -min_value = 1.0 -max_value = 1.0 -value = 1.0 - -[node name="NewBrushOptions" type="HBoxContainer" parent="VBoxContainer/HBoxContainer"] -visible = false -layout_mode = 2 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/NewBrushOptions"] -layout_mode = 2 -text = "Brush type:" - -[node name="BrushTypeOption" type="OptionButton" parent="VBoxContainer/HBoxContainer/NewBrushOptions"] -layout_mode = 2 -mouse_default_cursor_shape = 2 -item_count = 3 -selected = 0 -popup/item_0/text = "File brush" -popup/item_0/id = 0 -popup/item_1/text = "Project brush" -popup/item_1/id = 1 -popup/item_2/text = "Random brush" -popup/item_2/id = 2 - -[node name="BrushName" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/NewBrushOptions"] -visible = false -layout_mode = 2 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/NewBrushOptions/BrushName"] -layout_mode = 2 -text = "Brush name:" - -[node name="BrushNameLineEdit" type="LineEdit" parent="VBoxContainer/HBoxContainer/NewBrushOptions/BrushName"] -layout_mode = 2 - -[connection signal="about_to_popup" from="." to="." method="_on_PreviewDialog_about_to_show"] -[connection signal="confirmed" from="." to="." method="_on_PreviewDialog_confirmed"] -[connection signal="size_changed" from="." to="." method="_on_size_changed"] -[connection signal="visibility_changed" from="." to="." method="_on_visibility_changed"] -[connection signal="toggled" from="VBoxContainer/ApplyAll" to="." method="_on_ApplyAll_toggled"] -[connection signal="item_selected" from="VBoxContainer/HBoxContainer/ImportOption" to="." method="_on_ImportOption_item_selected"] -[connection signal="value_changed" from="VBoxContainer/HBoxContainer/SpritesheetTabOptions/Manual/HorizontalFrames" to="." method="_on_HorizontalFrames_value_changed"] -[connection signal="value_changed" from="VBoxContainer/HBoxContainer/SpritesheetTabOptions/Manual/VerticalFrames" to="." method="_on_VerticalFrames_value_changed"] -[connection signal="value_changed" from="VBoxContainer/HBoxContainer/SpritesheetTabOptions/SmartOptions/Threshold" to="." method="_on_threshold_value_changed"] -[connection signal="value_changed" from="VBoxContainer/HBoxContainer/SpritesheetTabOptions/SmartOptions/MergeDist" to="." method="_on_merge_dist_value_changed"] -[connection signal="pressed" from="VBoxContainer/HBoxContainer/SpritesheetTabOptions/SmartOptions/Slice" to="." method="_on_slice_pressed"] -[connection signal="toggled" from="VBoxContainer/HBoxContainer/SpritesheetTabOptions/SmartSliceButton" to="." method="_on_smart_slice_toggled"] -[connection signal="item_selected" from="VBoxContainer/HBoxContainer/NewBrushOptions/BrushTypeOption" to="." method="_on_BrushTypeOption_item_selected"]