init
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
@tool
|
||||
extends TabContainer
|
||||
|
||||
signal close_requested
|
||||
|
||||
const WizardWindow = preload("./as_wizard_window.tscn")
|
||||
|
||||
var _config
|
||||
var _file_system: EditorFileSystem
|
||||
|
||||
func _ready():
|
||||
$Import.init(_config, _file_system)
|
||||
$Import.connect("close_requested",Callable(self,"emit_signal").bind("close_requested"))
|
||||
$Import.connect("import_success",Callable($History,"add_entry"))
|
||||
$History.init(_config)
|
||||
$History.connect("request_edit",Callable(self,"_on_edit_request"))
|
||||
$History.connect("request_import",Callable(self,"_on_import_request"))
|
||||
|
||||
|
||||
func init(config, editor_file_system: EditorFileSystem):
|
||||
_config = config
|
||||
_file_system = editor_file_system
|
||||
|
||||
|
||||
func _on_AsWizardDockContainer_tab_changed(tab: int):
|
||||
if tab == 1:
|
||||
$History.reload()
|
||||
|
||||
|
||||
func _on_edit_request(import_cfg: Dictionary):
|
||||
$Import.load_import_config(import_cfg)
|
||||
self.current_tab = 0
|
||||
|
||||
|
||||
func _on_import_request(import_cfg: Dictionary):
|
||||
$Import.load_import_config(import_cfg)
|
||||
$Import.trigger_import()
|
||||
@@ -0,0 +1,26 @@
|
||||
[gd_scene load_steps=4 format=3]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://c5dwobjd34w3p" path="res://addons/AsepriteWizard/interface/docks/wizard/as_wizard_window.tscn" id="1"]
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/docks/wizard/as_wizard_dock_container.gd" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://cyoin5ncul0fm" path="res://addons/AsepriteWizard/interface/docks/wizard/sprite_frames_import_history.tscn" id="3"]
|
||||
|
||||
[node name="AsWizardDockContainer" type="TabContainer"]
|
||||
offset_right = 281.0
|
||||
offset_bottom = 36.0
|
||||
tab_alignment = 2
|
||||
use_hidden_tabs_for_min_size = true
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="Import" parent="." instance=ExtResource( 1 )]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 4.0
|
||||
offset_top = 32.0
|
||||
offset_right = -4.0
|
||||
offset_bottom = -4.0
|
||||
tooltip_text = "SpriteFrames Importer"
|
||||
|
||||
[node name="History" parent="." instance=ExtResource( 3 )]
|
||||
visible = false
|
||||
|
||||
[connection signal="tab_changed" from="." to="." method="_on_AsWizardDockContainer_tab_changed"]
|
||||
222
addons/AsepriteWizard/interface/docks/wizard/as_wizard_window.gd
Normal file
222
addons/AsepriteWizard/interface/docks/wizard/as_wizard_window.gd
Normal file
@@ -0,0 +1,222 @@
|
||||
@tool
|
||||
extends PanelContainer
|
||||
|
||||
signal close_requested
|
||||
signal import_success(file_settings)
|
||||
|
||||
var result_code = preload("../../../config/result_codes.gd")
|
||||
var _aseprite_file_exporter = preload("../../../aseprite/file_exporter.gd").new()
|
||||
var _sf_creator = preload("../../../creators/sprite_frames/sprite_frames_creator.gd").new()
|
||||
|
||||
var _config
|
||||
var _file_system: EditorFileSystem
|
||||
|
||||
var _file_dialog_aseprite: EditorFileDialog
|
||||
var _output_folder_dialog: EditorFileDialog
|
||||
var _warning_dialog: AcceptDialog
|
||||
|
||||
func _exit_tree():
|
||||
_file_dialog_aseprite.queue_free()
|
||||
_output_folder_dialog.queue_free()
|
||||
_warning_dialog.queue_free()
|
||||
|
||||
|
||||
func init(config, editor_file_system: EditorFileSystem):
|
||||
_config = config
|
||||
_file_system = editor_file_system
|
||||
_file_dialog_aseprite = _create_aseprite_file_selection()
|
||||
_output_folder_dialog = _create_outuput_folder_selection()
|
||||
_warning_dialog = AcceptDialog.new()
|
||||
_warning_dialog.exclusive = false
|
||||
|
||||
_sf_creator.init(_config)
|
||||
_aseprite_file_exporter.init(config)
|
||||
|
||||
get_parent().get_parent().add_child(_file_dialog_aseprite)
|
||||
get_parent().get_parent().add_child(_output_folder_dialog)
|
||||
get_parent().get_parent().add_child(_warning_dialog)
|
||||
|
||||
_load_persisted_config()
|
||||
|
||||
|
||||
func _load_persisted_config():
|
||||
_split_mode_field().button_pressed = _config.should_split_layers()
|
||||
_only_visible_layers_field().button_pressed = _config.should_include_only_visible_layers()
|
||||
_exception_pattern_field().text = _config.get_exception_pattern()
|
||||
_custom_name_field().text = _config.get_last_custom_name()
|
||||
_file_location_field().text = _config.get_last_source_path()
|
||||
_do_not_create_res_field().button_pressed = _config.should_not_create_resource()
|
||||
|
||||
var output_folder = _config.get_last_output_path()
|
||||
_output_folder_field().text = output_folder if output_folder != "" else "res://"
|
||||
|
||||
|
||||
func load_import_config(import_config: Dictionary):
|
||||
_split_mode_field().button_pressed = import_config.options.export_mode == _aseprite_file_exporter.LAYERS_EXPORT_MODE
|
||||
_only_visible_layers_field().button_pressed = import_config.options.only_visible_layers
|
||||
_exception_pattern_field().text = import_config.options.exception_pattern
|
||||
_custom_name_field().text = import_config.options.output_filename
|
||||
_file_location_field().text = import_config.source_file
|
||||
_do_not_create_res_field().button_pressed = import_config.options.do_not_create_resource
|
||||
_output_folder_field().text = import_config.output_location if import_config.output_location != "" else "res://"
|
||||
|
||||
|
||||
func _open_aseprite_file_selection_dialog():
|
||||
var current_selection = _file_location_field().text
|
||||
if current_selection != "":
|
||||
_file_dialog_aseprite.current_dir = current_selection.get_base_dir()
|
||||
_file_dialog_aseprite.popup_centered_ratio()
|
||||
|
||||
|
||||
func _open_output_folder_selection_dialog():
|
||||
var current_selection = _output_folder_field().text
|
||||
if current_selection != "":
|
||||
_output_folder_dialog.current_dir = current_selection
|
||||
_output_folder_dialog.popup_centered_ratio()
|
||||
|
||||
|
||||
func _create_aseprite_file_selection():
|
||||
var file_dialog = EditorFileDialog.new()
|
||||
file_dialog.file_mode = EditorFileDialog.FILE_MODE_OPEN_FILE
|
||||
file_dialog.access = EditorFileDialog.ACCESS_FILESYSTEM
|
||||
file_dialog.connect("file_selected", _on_aseprite_file_selected)
|
||||
file_dialog.set_filters(PackedStringArray(["*.ase","*.aseprite"]))
|
||||
return file_dialog
|
||||
|
||||
|
||||
func _create_outuput_folder_selection():
|
||||
var file_dialog = EditorFileDialog.new()
|
||||
file_dialog.file_mode = EditorFileDialog.FILE_MODE_OPEN_DIR
|
||||
file_dialog.access = EditorFileDialog.ACCESS_RESOURCES
|
||||
file_dialog.connect("dir_selected", _on_output_folder_selected)
|
||||
return file_dialog
|
||||
|
||||
|
||||
func _on_aseprite_file_selected(path):
|
||||
var localized_path = ProjectSettings.localize_path(path)
|
||||
_file_location_field().text = localized_path
|
||||
_config.set_last_source_path(localized_path)
|
||||
|
||||
|
||||
func _on_output_folder_selected(path):
|
||||
_output_folder_field().text = path
|
||||
_config.set_last_output_path(path)
|
||||
|
||||
|
||||
func _on_next_btn_up():
|
||||
var aseprite_file = _file_location_field().text
|
||||
var output_location = _output_folder_field().text
|
||||
var split_layers = _split_mode_field().button_pressed
|
||||
|
||||
var export_mode = _aseprite_file_exporter.LAYERS_EXPORT_MODE if split_layers else _aseprite_file_exporter.FILE_EXPORT_MODE
|
||||
var options = {
|
||||
"export_mode": export_mode,
|
||||
"exception_pattern": _exception_pattern_field().text,
|
||||
"only_visible_layers": _only_visible_layers_field().button_pressed,
|
||||
"output_filename": _custom_name_field().text,
|
||||
"do_not_create_resource": _do_not_create_res_field().button_pressed,
|
||||
"output_folder": output_location,
|
||||
}
|
||||
|
||||
var aseprite_output = _aseprite_file_exporter.generate_aseprite_files(
|
||||
ProjectSettings.globalize_path(aseprite_file),
|
||||
options
|
||||
)
|
||||
|
||||
if not aseprite_output.is_ok:
|
||||
_show_error(aseprite_output.code)
|
||||
return
|
||||
|
||||
_file_system.scan()
|
||||
await _file_system.filesystem_changed
|
||||
|
||||
var exit_code = OK
|
||||
|
||||
if !options.get("do_not_create_resource", false):
|
||||
exit_code = _sf_creator.create_and_save_resources(aseprite_output.content)
|
||||
|
||||
if _config.should_remove_source_files():
|
||||
_remove_source_files(aseprite_output.content)
|
||||
|
||||
if exit_code != OK:
|
||||
_show_error(exit_code)
|
||||
return
|
||||
|
||||
emit_signal("import_success", {
|
||||
"source_file": aseprite_file,
|
||||
"output_location": output_location,
|
||||
"options": options,
|
||||
})
|
||||
|
||||
_show_import_success_message()
|
||||
|
||||
|
||||
func trigger_import():
|
||||
_on_next_btn_up()
|
||||
|
||||
|
||||
func _on_close_btn_up():
|
||||
_close_window()
|
||||
|
||||
|
||||
func _close_window():
|
||||
_save_config()
|
||||
self.emit_signal("close_requested")
|
||||
|
||||
|
||||
func _save_config():
|
||||
_config.set_split_layers(_split_mode_field().button_pressed)
|
||||
_config.set_exception_pattern(_exception_pattern_field().text)
|
||||
_config.set_custom_name(_custom_name_field().text)
|
||||
_config.set_include_only_visible_layers(_only_visible_layers_field().button_pressed)
|
||||
_config.set_do_not_create_resource(_do_not_create_res_field().button_pressed)
|
||||
|
||||
|
||||
func _show_error(code: int):
|
||||
_show_error_message(result_code.get_error_message(code))
|
||||
|
||||
|
||||
func _show_error_message(message: String):
|
||||
_warning_dialog.dialog_text = "Error: %s" % message
|
||||
_warning_dialog.popup_centered()
|
||||
|
||||
|
||||
func _show_import_success_message():
|
||||
_warning_dialog.dialog_text = "Aseprite import succeeded"
|
||||
_warning_dialog.popup_centered()
|
||||
_save_config()
|
||||
|
||||
|
||||
func _file_location_field() -> LineEdit:
|
||||
return $container/options/file_location/HBoxContainer/file_location_path as LineEdit
|
||||
|
||||
|
||||
func _output_folder_field() -> LineEdit:
|
||||
return $container/options/output_folder/HBoxContainer/file_location_path as LineEdit
|
||||
|
||||
|
||||
func _exception_pattern_field() -> LineEdit:
|
||||
return $container/options/exclude_pattern/pattern as LineEdit
|
||||
|
||||
|
||||
func _split_mode_field() -> CheckBox:
|
||||
return $container/options/layer_importing_mode/split_layers/field as CheckBox
|
||||
|
||||
|
||||
func _only_visible_layers_field() -> CheckBox:
|
||||
return $container/options/layer_importing_mode/visible_layers/field as CheckBox
|
||||
|
||||
|
||||
func _custom_name_field() -> LineEdit:
|
||||
return $container/options/custom_filename/pattern as LineEdit
|
||||
|
||||
|
||||
func _do_not_create_res_field() -> CheckBox:
|
||||
return $container/options/layer_importing_mode/disable_resource_creation/field as CheckBox
|
||||
|
||||
|
||||
func _remove_source_files(source_files: Array):
|
||||
for s in source_files:
|
||||
DirAccess.remove_absolute(s.data_file)
|
||||
|
||||
_file_system.call_deferred("scan")
|
||||
@@ -0,0 +1,139 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://c5dwobjd34w3p"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/docks/wizard/as_wizard_window.gd" id="1"]
|
||||
|
||||
[node name="ASWizardWindow" type="PanelContainer"]
|
||||
offset_right = 600.0
|
||||
offset_bottom = 600.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 0
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="container" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="options" type="VBoxContainer" parent="container"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="file_location" type="VBoxContainer" parent="container/options"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="file_location_label" type="Label" parent="container/options/file_location"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Location of the Aseprite *.ase source file"
|
||||
mouse_filter = 1
|
||||
text = "Aseprite File Location:*"
|
||||
clip_text = true
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="container/options/file_location"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="file_location_path" type="LineEdit" parent="container/options/file_location/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
caret_blink = true
|
||||
|
||||
[node name="file_location_btn" type="Button" parent="container/options/file_location/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Select"
|
||||
|
||||
[node name="output_folder" type="VBoxContainer" parent="container/options"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="label" type="Label" parent="container/options/output_folder"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Folder where the SpriteSheet resource is going to be saved"
|
||||
mouse_filter = 1
|
||||
text = "Output folder:*"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="container/options/output_folder"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="file_location_path" type="LineEdit" parent="container/options/output_folder/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "res://"
|
||||
caret_blink = true
|
||||
|
||||
[node name="output_folder_btn" type="Button" parent="container/options/output_folder/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Select"
|
||||
|
||||
[node name="exclude_pattern" type="VBoxContainer" parent="container/options"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="label" type="Label" parent="container/options/exclude_pattern"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "If layer name matches this pattern, it won't be exported."
|
||||
mouse_filter = 1
|
||||
text = "Exclude layers with name matching pattern:"
|
||||
|
||||
[node name="pattern" type="LineEdit" parent="container/options/exclude_pattern"]
|
||||
layout_mode = 2
|
||||
caret_blink = true
|
||||
|
||||
[node name="custom_filename" type="VBoxContainer" parent="container/options"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="label" type="Label" parent="container/options/custom_filename"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Output filename. In case layers are not being merged, this is used as file prefix.
|
||||
If not set, source filename is used."
|
||||
mouse_filter = 1
|
||||
text = "Output file name / prefix:"
|
||||
|
||||
[node name="pattern" type="LineEdit" parent="container/options/custom_filename"]
|
||||
layout_mode = 2
|
||||
caret_blink = true
|
||||
|
||||
[node name="layer_importing_mode" type="VBoxContainer" parent="container/options"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="label" type="Label" parent="container/options/layer_importing_mode"]
|
||||
layout_mode = 2
|
||||
mouse_filter = 1
|
||||
text = "Options:"
|
||||
|
||||
[node name="split_layers" type="HBoxContainer" parent="container/options/layer_importing_mode"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="field" type="CheckBox" parent="container/options/layer_importing_mode/split_layers"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "If selected, one resource will be created for each layer.
|
||||
If not selected, layers will be merged and exported as one SpriteSheet."
|
||||
text = "Split layers in multiple resources"
|
||||
|
||||
[node name="visible_layers" type="HBoxContainer" parent="container/options/layer_importing_mode"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="field" type="CheckBox" parent="container/options/layer_importing_mode/visible_layers"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "If selected, layers not visible in the source file won't be included in the final image."
|
||||
text = "Only include visible layers"
|
||||
|
||||
[node name="disable_resource_creation" type="HBoxContainer" parent="container/options/layer_importing_mode"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="field" type="CheckBox" parent="container/options/layer_importing_mode/disable_resource_creation"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Does not create SpriteFrames resource. Useful if you are only interested in the .json and .png output from Aseprite."
|
||||
text = "Do not create resource file"
|
||||
|
||||
[node name="buttons" type="HBoxContainer" parent="container/options"]
|
||||
layout_mode = 2
|
||||
alignment = 2
|
||||
|
||||
[node name="close" type="Button" parent="container/options/buttons"]
|
||||
layout_mode = 2
|
||||
text = "Close"
|
||||
|
||||
[node name="next" type="Button" parent="container/options/buttons"]
|
||||
layout_mode = 2
|
||||
text = "Import"
|
||||
|
||||
[connection signal="button_up" from="container/options/file_location/HBoxContainer/file_location_btn" to="." method="_open_aseprite_file_selection_dialog"]
|
||||
[connection signal="button_up" from="container/options/output_folder/HBoxContainer/output_folder_btn" to="." method="_open_output_folder_selection_dialog"]
|
||||
[connection signal="button_up" from="container/options/buttons/close" to="." method="_on_close_btn_up"]
|
||||
[connection signal="button_up" from="container/options/buttons/next" to="." method="_on_next_btn_up"]
|
||||
@@ -0,0 +1,226 @@
|
||||
@tool
|
||||
extends PanelContainer
|
||||
|
||||
signal request_edit(import_cfg)
|
||||
signal request_import(import_cfg)
|
||||
|
||||
const SourcePathField = preload("./wizard_nodes/source_path.tscn")
|
||||
const OutputPathField = preload("./wizard_nodes/output_path.tscn")
|
||||
const ImportDateField = preload("./wizard_nodes/import_date.tscn")
|
||||
const ItemActions = preload("./wizard_nodes/list_actions.tscn")
|
||||
|
||||
const SORT_BY_DATE := 0
|
||||
const SORT_BY_PATH := 1
|
||||
const INITIAL_GRID_INDEX := 3
|
||||
|
||||
var _config
|
||||
var _history: Array
|
||||
var _history_nodes := {}
|
||||
var _history_nodes_list := []
|
||||
var _is_busy := false
|
||||
var _import_requested_for := -1
|
||||
var _sort_by = SORT_BY_DATE
|
||||
|
||||
@onready var grid = $MarginContainer/VBoxContainer/ScrollContainer/GridContainer
|
||||
@onready var loading_warning = $MarginContainer/VBoxContainer/loading_warning
|
||||
@onready var no_history_warning = $MarginContainer/VBoxContainer/no_history_warning
|
||||
|
||||
func init(config):
|
||||
_config = config
|
||||
|
||||
|
||||
func reload():
|
||||
if _history:
|
||||
return
|
||||
|
||||
_history = _config.get_import_history()
|
||||
|
||||
for index in range(_history.size()):
|
||||
var entry = _history[index]
|
||||
_create_node_list_entry(entry, index)
|
||||
|
||||
loading_warning.hide()
|
||||
if _history.is_empty():
|
||||
no_history_warning.show()
|
||||
else:
|
||||
grid.get_parent().show()
|
||||
|
||||
|
||||
func _create_node_list_entry(entry: Dictionary, index: int):
|
||||
_add_to_node_list(entry, _create_nodes(entry, index))
|
||||
|
||||
|
||||
func _create_nodes(entry: Dictionary, index: int) -> Dictionary:
|
||||
var source_path = SourcePathField.instantiate()
|
||||
source_path.set_entry(entry)
|
||||
|
||||
grid.get_child(INITIAL_GRID_INDEX).add_sibling(source_path)
|
||||
|
||||
var output_path = OutputPathField.instantiate()
|
||||
output_path.text = entry.output_location
|
||||
source_path.add_sibling(output_path)
|
||||
var import_date = ImportDateField.instantiate()
|
||||
import_date.set_date(entry.import_date)
|
||||
output_path.add_sibling(import_date)
|
||||
var actions = ItemActions.instantiate()
|
||||
actions.history_index = index
|
||||
import_date.add_sibling(actions)
|
||||
actions.connect("import_clicked",Callable(self,"_on_entry_reimport_clicked"))
|
||||
actions.connect("edit_clicked",Callable(self,"_on_entry_edit_clicked"))
|
||||
actions.connect("removed_clicked",Callable(self,"_on_entry_remove_clicked"))
|
||||
return {
|
||||
"history_index": index,
|
||||
"timestamp": entry.import_date,
|
||||
"source_file": entry.source_file,
|
||||
"source_path_node": source_path,
|
||||
"output_path_node": output_path,
|
||||
"import_date_node": import_date,
|
||||
"actions_node": actions,
|
||||
}
|
||||
|
||||
|
||||
func _add_to_node_list(entry: Dictionary, node: Dictionary):
|
||||
if not _history_nodes.has(entry.source_file):
|
||||
_history_nodes[entry.source_file] = []
|
||||
_history_nodes[entry.source_file].push_front(node)
|
||||
_history_nodes_list.push_front(node)
|
||||
|
||||
|
||||
func add_entry(file_settings: Dictionary):
|
||||
if _history == null:
|
||||
reload()
|
||||
|
||||
var dt = Time.get_datetime_dict_from_system()
|
||||
file_settings["import_date"] = "%04d-%02d-%02d %02d:%02d:%02d" % [dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second]
|
||||
|
||||
if _import_requested_for != -1:
|
||||
_remove_item(_import_requested_for)
|
||||
_import_requested_for = -1
|
||||
elif _config.is_single_file_history() and _history_nodes.has(file_settings.source_file):
|
||||
_remove_entries(file_settings.source_file)
|
||||
|
||||
_history.push_back(file_settings)
|
||||
_config.save_import_history(_history)
|
||||
_create_node_list_entry(file_settings, _history.size() - 1)
|
||||
|
||||
if _sort_by == SORT_BY_PATH:
|
||||
_trigger_sort()
|
||||
|
||||
no_history_warning.hide()
|
||||
loading_warning.hide()
|
||||
grid.get_parent().show()
|
||||
_is_busy = false
|
||||
|
||||
|
||||
func _on_entry_reimport_clicked(entry_index: int):
|
||||
if _is_busy:
|
||||
return
|
||||
_is_busy = true
|
||||
_import_requested_for = entry_index
|
||||
emit_signal("request_import", _history[entry_index])
|
||||
|
||||
|
||||
func _on_entry_edit_clicked(entry_index: int):
|
||||
if _is_busy:
|
||||
return
|
||||
emit_signal("request_edit", _history[entry_index])
|
||||
|
||||
|
||||
func _on_entry_remove_clicked(entry_index: int):
|
||||
if _is_busy:
|
||||
return
|
||||
_is_busy = true
|
||||
|
||||
_remove_item(entry_index)
|
||||
_config.save_import_history(_history)
|
||||
|
||||
if (_history.is_empty()):
|
||||
grid.get_parent().hide()
|
||||
no_history_warning.show()
|
||||
|
||||
_is_busy = false
|
||||
|
||||
|
||||
func _remove_item(entry_index: int):
|
||||
var entry = _history[entry_index]
|
||||
_remove_entries(entry.source_file, entry_index)
|
||||
|
||||
|
||||
# removes nodes and entry from history. If entry_index is not provided, all
|
||||
# entries for path are removed.
|
||||
func _remove_entries(source_file_path: String, entry_index: int = -1):
|
||||
var files_entries = _history_nodes[source_file_path]
|
||||
var indexes_to_remove = []
|
||||
|
||||
for f in files_entries:
|
||||
if entry_index == -1 or f.history_index == entry_index:
|
||||
_free_entry_nodes(f)
|
||||
_history_nodes_list.erase(f)
|
||||
|
||||
if entry_index != -1:
|
||||
files_entries.erase(f)
|
||||
_remove_from_history(f.history_index)
|
||||
return
|
||||
|
||||
indexes_to_remove.push_back(f.history_index)
|
||||
|
||||
for i in indexes_to_remove:
|
||||
_remove_from_history(i)
|
||||
|
||||
_history_nodes[source_file_path] = []
|
||||
|
||||
|
||||
func _remove_from_history(entry_index: int):
|
||||
var _already_adjusted = []
|
||||
# to avoid re-creating the whole nodes list, I just decrement
|
||||
# the index from items newer than the excluded one
|
||||
for index in range(entry_index + 1, _history.size()):
|
||||
if _already_adjusted.has(_history[index].source_file):
|
||||
continue
|
||||
_already_adjusted.push_back(_history[index].source_file)
|
||||
var nodes = _history_nodes[_history[index].source_file]
|
||||
for f in nodes:
|
||||
if f.history_index > entry_index:
|
||||
f.history_index -= 1
|
||||
f.actions_node.history_index = f.history_index
|
||||
|
||||
_history.remove_at(entry_index)
|
||||
|
||||
|
||||
func _free_entry_nodes(entry_history_node: Dictionary):
|
||||
entry_history_node.source_path_node.queue_free()
|
||||
entry_history_node.output_path_node.queue_free()
|
||||
entry_history_node.import_date_node.queue_free()
|
||||
entry_history_node.actions_node.queue_free()
|
||||
|
||||
|
||||
func _on_SortOptions_item_selected(index):
|
||||
if index == _sort_by:
|
||||
return
|
||||
|
||||
_trigger_sort(index)
|
||||
|
||||
|
||||
func _trigger_sort(sort_type: int = _sort_by):
|
||||
if sort_type == SORT_BY_DATE:
|
||||
_history_nodes_list.sort_custom(Callable(self,"_sort_by_date"))
|
||||
else:
|
||||
_history_nodes_list.sort_custom(Callable(self,"_sort_by_path"))
|
||||
_reorganise_nodes()
|
||||
_sort_by = sort_type
|
||||
|
||||
|
||||
func _sort_by_date(a, b):
|
||||
return a.timestamp < b.timestamp
|
||||
|
||||
|
||||
func _sort_by_path(a, b):
|
||||
return a.source_file > b.source_file
|
||||
|
||||
|
||||
func _reorganise_nodes():
|
||||
for entry in _history_nodes_list:
|
||||
grid.move_child(entry.source_path_node, INITIAL_GRID_INDEX + 1)
|
||||
grid.move_child(entry.output_path_node, INITIAL_GRID_INDEX + 2)
|
||||
grid.move_child(entry.import_date_node, INITIAL_GRID_INDEX + 3)
|
||||
grid.move_child(entry.actions_node, INITIAL_GRID_INDEX + 4)
|
||||
@@ -0,0 +1,81 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cyoin5ncul0fm"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/docks/wizard/sprite_frames_import_history.gd" id="1"]
|
||||
|
||||
[node name="SpriteFramesImportHistory" type="PanelContainer"]
|
||||
anchors_preset = 10
|
||||
anchor_right = 1.0
|
||||
grow_horizontal = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="list actions" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
alignment = 2
|
||||
|
||||
[node name="divider" type="Label" parent="MarginContainer/VBoxContainer/list actions"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="sort_label" type="Label" parent="MarginContainer/VBoxContainer/list actions"]
|
||||
layout_mode = 2
|
||||
text = "Sort by:"
|
||||
|
||||
[node name="SortOptions" type="OptionButton" parent="MarginContainer/VBoxContainer/list actions"]
|
||||
layout_mode = 2
|
||||
item_count = 2
|
||||
selected = 0
|
||||
popup/item_0/text = "Date"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "Name"
|
||||
popup/item_1/id = 1
|
||||
|
||||
[node name="loading_warning" type="Label" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 6
|
||||
text = "Loading..."
|
||||
|
||||
[node name="no_history_warning" type="Label" parent="MarginContainer/VBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 6
|
||||
text = "No import history"
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="MarginContainer/VBoxContainer/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
columns = 4
|
||||
|
||||
[node name="source_label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
text = "Source File"
|
||||
|
||||
[node name="output_label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
text = "Output Folder"
|
||||
|
||||
[node name="date_label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
text = "Date"
|
||||
|
||||
[node name="actions_label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
text = "Actions"
|
||||
|
||||
[connection signal="item_selected" from="MarginContainer/VBoxContainer/list actions/SortOptions" to="." method="_on_SortOptions_item_selected"]
|
||||
@@ -0,0 +1,12 @@
|
||||
@tool
|
||||
extends Label
|
||||
|
||||
|
||||
func set_date(timestamp: String):
|
||||
self.text = timestamp
|
||||
# self.text = _format_date(timestamp)
|
||||
|
||||
|
||||
#func _format_date(timestamp: int) -> String:
|
||||
# var dt = Time.get_datetime_dict_from_system_from_unix_time(timestamp)
|
||||
# return "%04d-%02d-%02d %02d:%02d:%02d" % [dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second]
|
||||
@@ -0,0 +1,11 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/docks/wizard/wizard_nodes/import_date.gd" id="1"]
|
||||
|
||||
[node name="import_date" type="Label"]
|
||||
offset_left = 660.0
|
||||
offset_top = 39.0
|
||||
offset_right = 774.0
|
||||
offset_bottom = 53.0
|
||||
text = "2022-07-18 18:01"
|
||||
script = ExtResource( 1 )
|
||||
@@ -0,0 +1,20 @@
|
||||
@tool
|
||||
extends HBoxContainer
|
||||
|
||||
signal import_clicked(index)
|
||||
signal edit_clicked(index)
|
||||
signal removed_clicked(index)
|
||||
|
||||
var history_index = -1
|
||||
|
||||
|
||||
func _on_edit_pressed():
|
||||
emit_signal("edit_clicked", history_index)
|
||||
|
||||
|
||||
func _on_reimport_pressed():
|
||||
emit_signal("import_clicked", history_index)
|
||||
|
||||
|
||||
func _on_remove_pressed():
|
||||
emit_signal("removed_clicked", history_index)
|
||||
@@ -0,0 +1,35 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/docks/wizard/wizard_nodes/list_actions.gd" id="1"]
|
||||
|
||||
[node name="actions" type="HBoxContainer"]
|
||||
offset_left = 784.0
|
||||
offset_top = 34.0
|
||||
offset_right = 950.0
|
||||
offset_bottom = 58.0
|
||||
custom_constants/separation = 5
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="edit" type="Button" parent="."]
|
||||
offset_right = 36.0
|
||||
offset_bottom = 20.0
|
||||
size_flags_vertical = 0
|
||||
text = "Edit"
|
||||
|
||||
[node name="reimport" type="Button" parent="."]
|
||||
offset_left = 41.0
|
||||
offset_right = 97.0
|
||||
offset_bottom = 20.0
|
||||
size_flags_vertical = 0
|
||||
text = "Import"
|
||||
|
||||
[node name="remove_at" type="Button" parent="."]
|
||||
offset_left = 102.0
|
||||
offset_right = 166.0
|
||||
offset_bottom = 20.0
|
||||
size_flags_vertical = 0
|
||||
text = "Remove"
|
||||
|
||||
[connection signal="pressed" from="edit" to="." method="_on_edit_pressed"]
|
||||
[connection signal="pressed" from="reimport" to="." method="_on_reimport_pressed"]
|
||||
[connection signal="pressed" from="remove_at" to="." method="_on_remove_pressed"]
|
||||
@@ -0,0 +1,12 @@
|
||||
[gd_scene format=2]
|
||||
|
||||
[node name="output_path" type="LineEdit"]
|
||||
offset_left = 450.0
|
||||
offset_top = 34.0
|
||||
offset_right = 650.0
|
||||
offset_bottom = 58.0
|
||||
minimum_size = Vector2( 200, 0 )
|
||||
size_flags_vertical = 0
|
||||
text = "/some/output"
|
||||
align = 3
|
||||
editable = false
|
||||
@@ -0,0 +1,22 @@
|
||||
@tool
|
||||
extends LineEdit
|
||||
|
||||
|
||||
func set_entry(entry: Dictionary):
|
||||
self.text = entry.source_file
|
||||
self.tooltip_text = _format_hint(entry)
|
||||
|
||||
|
||||
func _format_hint(entry: Dictionary) -> String:
|
||||
return """Output filename/prefix: %s
|
||||
Ex. pattern: %s
|
||||
Split: %s
|
||||
Only visible: %s
|
||||
No Resource: %s
|
||||
""" % [
|
||||
entry.options.output_filename,
|
||||
entry.options.exception_pattern,
|
||||
"yes" if entry.options.export_mode else "no",
|
||||
"yes" if entry.options.only_visible_layers else "no",
|
||||
"yes" if entry.options.do_not_create_resource else "no",
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/docks/wizard/wizard_nodes/source_path.gd" id="1"]
|
||||
|
||||
[node name="source_path" type="LineEdit"]
|
||||
offset_top = 34.0
|
||||
offset_right = 440.0
|
||||
offset_bottom = 58.0
|
||||
minimum_size = Vector2( 200, 0 )
|
||||
tooltip_text = "Output name / prefix: some_name
|
||||
Ex. Pattern: $_
|
||||
Split: Yes
|
||||
Only Visible: No
|
||||
No Resource: No"
|
||||
size_flags_vertical = 0
|
||||
text = "/some/very/long/source/path/to/test/field"
|
||||
editable = false
|
||||
script = ExtResource( 1 )
|
||||
Reference in New Issue
Block a user