init
This commit is contained in:
413
addons/AsepriteWizard/interface/docks/base_inspector_dock.gd
Normal file
413
addons/AsepriteWizard/interface/docks/base_inspector_dock.gd
Normal file
@@ -0,0 +1,413 @@
|
||||
@tool
|
||||
extends PanelContainer
|
||||
|
||||
const wizard_config = preload("../../config/wizard_config.gd")
|
||||
const result_code = preload("../../config/result_codes.gd")
|
||||
var _aseprite_file_exporter = preload("../../aseprite/file_exporter.gd").new()
|
||||
|
||||
var scene: Node
|
||||
var target_node: Node
|
||||
var config
|
||||
var file_system: EditorFileSystem
|
||||
|
||||
var _layer: String = ""
|
||||
var _slice: String = ""
|
||||
var _source: String = ""
|
||||
var _file_dialog_aseprite: EditorFileDialog
|
||||
var _output_folder_dialog: EditorFileDialog
|
||||
var _importing := false
|
||||
var _output_folder := ""
|
||||
var _out_folder_default := "[Same as scene]"
|
||||
var _layer_default := "[all]"
|
||||
|
||||
var _interface_section_state
|
||||
|
||||
@onready var _section_title := $dock_fields/VBoxContainer/title as Button
|
||||
|
||||
# general
|
||||
@onready var _source_field := $dock_fields/VBoxContainer/source/button as Button
|
||||
# layers
|
||||
@onready var _layer_section_header := $dock_fields/VBoxContainer/extra/sections/layers/section_header as Button
|
||||
@onready var _layer_section_container := $dock_fields/VBoxContainer/extra/sections/layers/section_content as MarginContainer
|
||||
@onready var _layer_field := $dock_fields/VBoxContainer/extra/sections/layers/section_content/content/layer/options as OptionButton
|
||||
@onready var _visible_layers_field := $dock_fields/VBoxContainer/extra/sections/layers/section_content/content/visible_layers/CheckBox as CheckBox
|
||||
@onready var _ex_pattern_field := $dock_fields/VBoxContainer/extra/sections/layers/section_content/content/ex_pattern/LineEdit as LineEdit
|
||||
# slice
|
||||
@onready var _slice_section_header := $dock_fields/VBoxContainer/extra/sections/slices/section_header as Button
|
||||
@onready var _slice_section_container := $dock_fields/VBoxContainer/extra/sections/slices/section_content as MarginContainer
|
||||
@onready var _slice_field := $dock_fields/VBoxContainer/extra/sections/slices/section_content/content/slice/options as OptionButton
|
||||
# output
|
||||
@onready var _output_section_header := $dock_fields/VBoxContainer/extra/sections/output/section_header as Button
|
||||
@onready var _output_section_container := $dock_fields/VBoxContainer/extra/sections/output/section_content as MarginContainer
|
||||
@onready var _out_folder_field := $dock_fields/VBoxContainer/extra/sections/output/section_content/content/out_folder/button as Button
|
||||
@onready var _out_filename_field := $dock_fields/VBoxContainer/extra/sections/output/section_content/content/out_filename/LineEdit as LineEdit
|
||||
|
||||
@onready var _import_button := $dock_fields/VBoxContainer/import as Button
|
||||
|
||||
const INTERFACE_SECTION_KEY_LAYER = "layer_section"
|
||||
const INTERFACE_SECTION_KEY_SLICE = "slice_section"
|
||||
const INTERFACE_SECTION_KEY_OUTPUT = "output_section"
|
||||
|
||||
@onready var _expandable_sections = {
|
||||
INTERFACE_SECTION_KEY_LAYER: { "header": _layer_section_header, "content": _layer_section_container},
|
||||
INTERFACE_SECTION_KEY_SLICE: { "header": _slice_section_header, "content": _slice_section_container},
|
||||
INTERFACE_SECTION_KEY_OUTPUT: { "header": _output_section_header, "content": _output_section_container},
|
||||
}
|
||||
|
||||
func _ready():
|
||||
_pre_setup()
|
||||
_setup_interface()
|
||||
_setup_config()
|
||||
_aseprite_file_exporter.init(config)
|
||||
_setup_field_listeners()
|
||||
_setup()
|
||||
|
||||
func _setup_interface():
|
||||
_hide_fields()
|
||||
_show_specific_fields()
|
||||
var cfg = wizard_config.load_interface_config(target_node)
|
||||
_interface_section_state = cfg
|
||||
|
||||
_section_title.add_theme_stylebox_override("normal", _section_title.get_theme_stylebox("hover"))
|
||||
|
||||
for key in _expandable_sections:
|
||||
_adjust_section_visibility(key)
|
||||
|
||||
|
||||
func _setup_config():
|
||||
var cfg = wizard_config.load_config(target_node)
|
||||
if cfg == null:
|
||||
_load_common_default_config()
|
||||
else:
|
||||
_load_common_config(cfg)
|
||||
|
||||
|
||||
func _load_common_config(cfg):
|
||||
if cfg.has("source"):
|
||||
_set_source(cfg.source)
|
||||
|
||||
if cfg.get("layer", "") != "":
|
||||
_layer_field.clear()
|
||||
_set_layer(cfg.layer)
|
||||
|
||||
if cfg.get("slice", "") != "":
|
||||
_slice_field.clear()
|
||||
_set_slice(cfg.slice)
|
||||
|
||||
_set_out_folder(cfg.get("o_folder", ""))
|
||||
_out_filename_field.text = cfg.get("o_name", "")
|
||||
_visible_layers_field.button_pressed = cfg.get("only_visible", false)
|
||||
_ex_pattern_field.text = cfg.get("o_ex_p", "")
|
||||
|
||||
_load_config(cfg)
|
||||
|
||||
|
||||
func _load_common_default_config():
|
||||
_ex_pattern_field.text = config.get_default_exclusion_pattern()
|
||||
_visible_layers_field.button_pressed = config.should_include_only_visible_layers_by_default()
|
||||
#_cleanup_hide_unused_nodes.button_pressed = config.is_set_visible_track_automatically_enabled()
|
||||
_load_default_config()
|
||||
|
||||
|
||||
func _set_source(source):
|
||||
_source = source
|
||||
_source_field.text = _source
|
||||
_source_field.tooltip_text = _source
|
||||
|
||||
|
||||
func _set_layer(layer):
|
||||
_layer = layer
|
||||
_layer_field.add_item(_layer)
|
||||
|
||||
|
||||
func _set_slice(slice):
|
||||
_slice = slice
|
||||
_slice_field.add_item(_slice)
|
||||
|
||||
|
||||
func _set_out_folder(path):
|
||||
_output_folder = path
|
||||
_out_folder_field.text = _output_folder if _output_folder != "" else _out_folder_default
|
||||
_out_folder_field.tooltip_text = _out_folder_field.text
|
||||
|
||||
|
||||
func _toggle_section_visibility(key: String) -> void:
|
||||
_interface_section_state[key] = not _interface_section_state.get(key, false)
|
||||
_adjust_section_visibility(key)
|
||||
wizard_config.save_interface_config(target_node, _interface_section_state)
|
||||
|
||||
|
||||
func _adjust_section_visibility(key: String) -> void:
|
||||
var section = _expandable_sections[key]
|
||||
var is_visible = _interface_section_state.get(key, false)
|
||||
_adjust_icon(section.header, is_visible)
|
||||
section.content.visible = is_visible
|
||||
|
||||
|
||||
func _adjust_icon(section: Button, is_visible: bool = true) -> void:
|
||||
var icon_name = "GuiTreeArrowDown" if is_visible else "GuiTreeArrowRight"
|
||||
section.icon = get_theme_icon(icon_name, "EditorIcons")
|
||||
|
||||
|
||||
func _setup_field_listeners():
|
||||
_layer_section_header.button_down.connect(_on_layer_header_button_down)
|
||||
_slice_section_header.button_down.connect(_on_slice_header_button_down)
|
||||
_output_section_header.button_down.connect(_on_output_header_button_down)
|
||||
|
||||
_source_field.pressed.connect(_on_source_pressed)
|
||||
_source_field.aseprite_file_dropped.connect(_on_source_aseprite_file_dropped)
|
||||
|
||||
_layer_field.button_down.connect(_on_layer_button_down)
|
||||
_layer_field.item_selected.connect(_on_layer_item_selected)
|
||||
|
||||
_slice_field.button_down.connect(_on_slice_button_down)
|
||||
_slice_field.item_selected.connect(_on_slice_item_selected)
|
||||
|
||||
_out_folder_field.dir_dropped.connect(_on_out_dir_dropped)
|
||||
_out_folder_field.pressed.connect(_on_out_folder_pressed)
|
||||
|
||||
_import_button.pressed.connect(_on_import_pressed)
|
||||
|
||||
|
||||
func _on_layer_header_button_down():
|
||||
_toggle_section_visibility(INTERFACE_SECTION_KEY_LAYER)
|
||||
|
||||
|
||||
func _on_slice_header_button_down():
|
||||
_toggle_section_visibility(INTERFACE_SECTION_KEY_SLICE)
|
||||
|
||||
|
||||
func _on_output_header_button_down():
|
||||
_toggle_section_visibility(INTERFACE_SECTION_KEY_OUTPUT)
|
||||
|
||||
|
||||
func _on_layer_button_down():
|
||||
if _source == "":
|
||||
_show_message("Please. Select source file first.")
|
||||
return
|
||||
|
||||
var layers = _get_available_layers(ProjectSettings.globalize_path(_source))
|
||||
_populate_options_field(_layer_field, layers, _layer)
|
||||
|
||||
|
||||
func _on_layer_item_selected(index):
|
||||
if index == 0:
|
||||
_layer = ""
|
||||
return
|
||||
_layer = _layer_field.get_item_text(index)
|
||||
_save_config()
|
||||
|
||||
|
||||
func _on_slice_item_selected(index):
|
||||
if index == 0:
|
||||
_slice = ""
|
||||
return
|
||||
_slice = _slice_field.get_item_text(index)
|
||||
_save_config()
|
||||
|
||||
|
||||
func _on_slice_button_down():
|
||||
if _source == "":
|
||||
_show_message("Please, select source file first.")
|
||||
return
|
||||
|
||||
var slices = _get_available_slices(ProjectSettings.globalize_path(_source))
|
||||
var current = 0
|
||||
_slice_field.clear()
|
||||
_slice_field.add_item(_layer_default)
|
||||
|
||||
for s in slices:
|
||||
if s == "":
|
||||
continue
|
||||
|
||||
_slice_field.add_item(s)
|
||||
if s == _slice:
|
||||
current = _slice_field.get_item_count() - 1
|
||||
_slice_field.select(current)
|
||||
|
||||
|
||||
func _on_source_pressed():
|
||||
_open_source_dialog()
|
||||
|
||||
##
|
||||
## Save current import options to node metadata
|
||||
##
|
||||
func _save_config():
|
||||
var child_config = _get_current_field_values()
|
||||
|
||||
var cfg := {
|
||||
"source": _source,
|
||||
"layer": _layer,
|
||||
"slice": _slice,
|
||||
"o_folder": _output_folder,
|
||||
"o_name": _out_filename_field.text,
|
||||
"only_visible": _visible_layers_field.button_pressed,
|
||||
"o_ex_p": _ex_pattern_field.text,
|
||||
}
|
||||
|
||||
for c in child_config:
|
||||
cfg[c] = child_config[c]
|
||||
|
||||
wizard_config.save_config(target_node, config.is_use_metadata_enabled(), cfg)
|
||||
|
||||
|
||||
func _get_import_options(default_folder: String):
|
||||
return {
|
||||
"output_folder": _output_folder if _output_folder != "" else default_folder,
|
||||
"exception_pattern": _ex_pattern_field.text,
|
||||
"only_visible_layers": _visible_layers_field.button_pressed,
|
||||
"output_filename": _out_filename_field.text,
|
||||
"layer": _layer
|
||||
}
|
||||
|
||||
|
||||
func _open_source_dialog():
|
||||
_file_dialog_aseprite = _create_aseprite_file_selection()
|
||||
get_parent().add_child(_file_dialog_aseprite)
|
||||
if _source != "":
|
||||
_file_dialog_aseprite.current_dir = ProjectSettings.globalize_path(_source.get_base_dir())
|
||||
_file_dialog_aseprite.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",Callable(self,"_on_aseprite_file_selected"))
|
||||
file_dialog.set_filters(PackedStringArray(["*.ase","*.aseprite"]))
|
||||
return file_dialog
|
||||
|
||||
|
||||
func _on_aseprite_file_selected(path):
|
||||
_set_source(ProjectSettings.localize_path(path))
|
||||
_save_config()
|
||||
_file_dialog_aseprite.queue_free()
|
||||
|
||||
|
||||
func _on_source_aseprite_file_dropped(path):
|
||||
_set_source(path)
|
||||
_save_config()
|
||||
|
||||
|
||||
## Helper method to populate field with values
|
||||
func _populate_options_field(field: OptionButton, values: Array, current_name: String):
|
||||
var current = 0
|
||||
field.clear()
|
||||
field.add_item("[all]")
|
||||
|
||||
for v in values:
|
||||
if v == "":
|
||||
continue
|
||||
|
||||
field.add_item(v)
|
||||
if v == current_name:
|
||||
current = field.get_item_count() - 1
|
||||
field.select(current)
|
||||
|
||||
|
||||
func _on_out_folder_pressed():
|
||||
_output_folder_dialog = _create_output_folder_selection()
|
||||
get_parent().add_child(_output_folder_dialog)
|
||||
if _output_folder != _out_folder_default:
|
||||
_output_folder_dialog.current_dir = _output_folder
|
||||
_output_folder_dialog.popup_centered_ratio()
|
||||
|
||||
|
||||
func _create_output_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",Callable(self,"_on_output_folder_selected"))
|
||||
return file_dialog
|
||||
|
||||
|
||||
func _on_output_folder_selected(path):
|
||||
_set_out_folder(path)
|
||||
_output_folder_dialog.queue_free()
|
||||
|
||||
|
||||
func _on_out_dir_dropped(path):
|
||||
_set_out_folder(path)
|
||||
|
||||
|
||||
func _show_message(message: String):
|
||||
var _warning_dialog = AcceptDialog.new()
|
||||
get_parent().add_child(_warning_dialog)
|
||||
_warning_dialog.dialog_text = message
|
||||
_warning_dialog.popup_centered()
|
||||
_warning_dialog.connect("popup_hide",Callable(_warning_dialog,"queue_free"))
|
||||
|
||||
|
||||
func _notify_aseprite_error(aseprite_error_code):
|
||||
var error = result_code.get_error_message(aseprite_error_code)
|
||||
printerr(error)
|
||||
_show_message(error)
|
||||
|
||||
|
||||
func _handle_cleanup(aseprite_content):
|
||||
if config.should_remove_source_files():
|
||||
DirAccess.remove_absolute(aseprite_content.data_file)
|
||||
file_system.call_deferred("scan")
|
||||
|
||||
|
||||
func _on_import_pressed():
|
||||
if _importing:
|
||||
return
|
||||
_importing = true
|
||||
|
||||
if _source == "":
|
||||
_show_message("Aseprite file not selected")
|
||||
_importing = false
|
||||
return
|
||||
|
||||
await _do_import()
|
||||
_importing = false
|
||||
|
||||
|
||||
# This is a little bit leaky as this base scene contains fields only relevant to animation players.
|
||||
# However, this is the simplest thing I can do without overcomplicating stuff.
|
||||
func _hide_fields():
|
||||
$dock_fields/VBoxContainer/modes.hide()
|
||||
$dock_fields/VBoxContainer/animation_player.hide()
|
||||
$dock_fields/VBoxContainer/extra/sections/animation.hide()
|
||||
|
||||
|
||||
## this will be called before base class does its setup
|
||||
func _pre_setup():
|
||||
pass
|
||||
|
||||
|
||||
## this will be called after base class setup is complete
|
||||
func _setup():
|
||||
pass
|
||||
|
||||
|
||||
func _load_default_config():
|
||||
pass
|
||||
|
||||
|
||||
func _load_config(cfg: Dictionary):
|
||||
pass
|
||||
|
||||
|
||||
## Override to return available layers
|
||||
func _get_available_layers(global_source_path: String) -> Array:
|
||||
return []
|
||||
|
||||
|
||||
## Override to return available slices
|
||||
func _get_available_slices(global_source_path: String) -> Array:
|
||||
return []
|
||||
|
||||
|
||||
## Override this method for extra import options to add to node metadata
|
||||
func _get_current_field_values() -> Dictionary:
|
||||
return {}
|
||||
|
||||
|
||||
func _do_import():
|
||||
pass
|
||||
|
||||
|
||||
func _show_specific_fields() -> void:
|
||||
pass
|
||||
Reference in New Issue
Block a user