init
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
@tool
|
||||
extends Window
|
||||
|
||||
func _on_close_requested():
|
||||
self.queue_free()
|
||||
@@ -0,0 +1,14 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://0x3mlxsex7eb"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/imports_manager/aseprite_imports_manager.gd" id="1_wrm15"]
|
||||
|
||||
[node name="AsepriteDockImportsWindow" type="Window"]
|
||||
title = "Aseprite Imports Manager"
|
||||
initial_position = 1
|
||||
size = Vector2i(612, 458)
|
||||
wrap_controls = true
|
||||
transient = true
|
||||
min_size = Vector2i(600, 400)
|
||||
script = ExtResource("1_wrm15")
|
||||
|
||||
[connection signal="close_requested" from="." to="." method="_on_close_requested"]
|
||||
@@ -0,0 +1,330 @@
|
||||
@tool
|
||||
extends Panel
|
||||
|
||||
const wizard_config = preload("../../config/wizard_config.gd")
|
||||
|
||||
var _import_helper = preload("./import_helper.gd").new()
|
||||
|
||||
@onready var _tree_container = $MarginContainer/VBoxContainer/HSplitContainer/tree
|
||||
@onready var _resource_tree = _tree_container.get_resource_tree()
|
||||
@onready var _details = $MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer
|
||||
|
||||
@onready var _nothing_container = $MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/nothing
|
||||
@onready var _single_item_container = $MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/single_item
|
||||
@onready var _multiple_items_container = $MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/multiple_items
|
||||
|
||||
@onready var _confirmation_warning_container = $MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/confirmation_warning
|
||||
|
||||
const supported_types = [
|
||||
"Sprite2D",
|
||||
"Sprite3D",
|
||||
"AnimatedSprite2D",
|
||||
"AnimatedSprite3D",
|
||||
"TextureRect",
|
||||
]
|
||||
|
||||
var _selection_count = 0
|
||||
var _current_buttons_container
|
||||
var _resources_to_process
|
||||
|
||||
var _should_save_in = 0
|
||||
|
||||
|
||||
func _ready():
|
||||
_set_empty_details_state()
|
||||
|
||||
var file_tree = _get_file_tree("res://")
|
||||
_setup_tree(file_tree)
|
||||
|
||||
|
||||
# Unfortunately godot throws some nasty warnings when trying to save after
|
||||
# multiple import operations. I implemented this late save as a workaround
|
||||
func _process(delta):
|
||||
if _should_save_in > 0:
|
||||
_should_save_in -= delta
|
||||
if _should_save_in <= 0:
|
||||
_should_save_in = 0
|
||||
_save_all_scenes()
|
||||
|
||||
|
||||
func _get_file_tree(base_path: String, dir_name: String = "") -> Dictionary:
|
||||
var dir_path = base_path.path_join(dir_name)
|
||||
var dir = DirAccess.open(dir_path)
|
||||
var dir_data = { "path": dir_path, "name": dir_name, "children": [], "type": "dir", }
|
||||
if not dir:
|
||||
return dir_data
|
||||
|
||||
dir.list_dir_begin()
|
||||
var file_name = dir.get_next()
|
||||
|
||||
while file_name != "":
|
||||
if dir.current_is_dir() and _is_importable_folder(dir_path, file_name):
|
||||
var child_data = _get_file_tree(dir_path, file_name)
|
||||
if not child_data.children.is_empty():
|
||||
dir_data.children.push_back(child_data)
|
||||
elif file_name.ends_with(".tscn"):
|
||||
var file_path = dir_path.path_join(file_name)
|
||||
var metadata = _get_aseprite_metadata(file_path)
|
||||
if not metadata.is_empty():
|
||||
dir_data.children.push_back({
|
||||
"name": file_name,
|
||||
"path": file_path,
|
||||
"resources": metadata,
|
||||
"type": "file",
|
||||
})
|
||||
|
||||
file_name = dir.get_next()
|
||||
|
||||
return dir_data
|
||||
|
||||
|
||||
func _is_importable_folder(dir_path: String, dir_name: String) -> bool:
|
||||
return dir_path != "res://" or dir_name != "addons"
|
||||
|
||||
|
||||
func _setup_tree(resource_tree: Dictionary) -> void:
|
||||
_resource_tree.set_column_title(0, "Resource")
|
||||
|
||||
var root = _resource_tree.create_item()
|
||||
|
||||
_add_items_to_tree(root, resource_tree.children)
|
||||
|
||||
|
||||
func _add_items_to_tree(root: TreeItem, children: Array):
|
||||
for node in children:
|
||||
var item: TreeItem = _resource_tree.create_item(root)
|
||||
item.set_text(0, node.name)
|
||||
item.set_meta("node", node)
|
||||
match node.type:
|
||||
"dir":
|
||||
item.set_icon(0, get_theme_icon("Folder", "EditorIcons"))
|
||||
_add_items_to_tree(item, node.children)
|
||||
|
||||
"file":
|
||||
item.set_icon(0, get_theme_icon("PackedScene", "EditorIcons"))
|
||||
_add_items_to_tree(item, node.resources)
|
||||
|
||||
"resource":
|
||||
item.set_icon(0, get_theme_icon(node.node_type, "EditorIcons"))
|
||||
if node.has_changes:
|
||||
item.set_text(0, "%s (*)" % node.name)
|
||||
|
||||
|
||||
func _get_aseprite_metadata(file_path: String) -> Array:
|
||||
var scene: PackedScene = load(file_path)
|
||||
var root = scene.instantiate()
|
||||
var state = scene.get_state()
|
||||
|
||||
var resources = []
|
||||
for i in range(state.get_node_count()):
|
||||
var node_type = state.get_node_type(i)
|
||||
if _is_supported_type(node_type):
|
||||
var node_path = state.get_node_path(i)
|
||||
var target_node = root.get_node(node_path)
|
||||
var meta = wizard_config.load_config(target_node)
|
||||
if meta != null:
|
||||
resources.push_back({
|
||||
"type": "resource",
|
||||
"node_type": node_type,
|
||||
"name": node_path,
|
||||
"node_path": node_path,
|
||||
"node_name": state.get_node_name(i),
|
||||
"meta": meta,
|
||||
"scene_path": file_path,
|
||||
"has_changes": _has_source_changes(target_node, meta.get("source"))
|
||||
})
|
||||
|
||||
return resources
|
||||
|
||||
|
||||
func _has_source_changes(target_node: Node, source_path: String) -> bool:
|
||||
if not source_path or source_path == "":
|
||||
return false
|
||||
var saved_hash = wizard_config.get_source_hash(target_node)
|
||||
if saved_hash == "":
|
||||
return false
|
||||
var current_hash = FileAccess.get_md5(source_path)
|
||||
|
||||
return saved_hash != current_hash
|
||||
|
||||
|
||||
func _is_supported_type(node_type: String) -> bool:
|
||||
return supported_types.has(node_type)
|
||||
|
||||
|
||||
func _open_scene(item: TreeItem) -> void:
|
||||
var meta = item.get_meta("node")
|
||||
if meta:
|
||||
EditorInterface.open_scene_from_path(meta.path)
|
||||
|
||||
|
||||
func _trigger_import(meta: Dictionary) -> void:
|
||||
# A more elegant way would have been to change the PackedScene directly, however
|
||||
# during my attempts changing external resources this way was buggy. I decided
|
||||
# to open and edit the scene via editor with the caveat of having to keep it open afterwards.
|
||||
EditorInterface.open_scene_from_path(meta.scene_path)
|
||||
|
||||
var root_node = EditorInterface.get_edited_scene_root()
|
||||
|
||||
if not root_node:
|
||||
printerr("couldn´t open scene %s" % meta.scene_path)
|
||||
|
||||
await _import_helper.import_node(root_node, meta)
|
||||
|
||||
print("Import complete: %s (%s) node from %s" % [ meta.node_path, meta.meta.source, meta.scene_path])
|
||||
|
||||
|
||||
func _on_resource_tree_multi_selected(_item: TreeItem, _column: int, selected: bool) -> void:
|
||||
_confirmation_warning_container.hide()
|
||||
_resources_to_process = null
|
||||
if _current_buttons_container != null:
|
||||
_current_buttons_container.show_buttons()
|
||||
|
||||
if selected:
|
||||
_selection_count += 1
|
||||
else:
|
||||
_selection_count -= 1
|
||||
|
||||
_nothing_container.hide()
|
||||
_single_item_container.hide()
|
||||
_multiple_items_container.hide()
|
||||
|
||||
match _selection_count:
|
||||
0:
|
||||
_nothing_container.show()
|
||||
1:
|
||||
_single_item_container.show()
|
||||
_set_item_details(_resource_tree.get_selected())
|
||||
_current_buttons_container = _single_item_container
|
||||
_:
|
||||
_multiple_items_container.show()
|
||||
_multiple_items_container.set_selected_count(_selection_count)
|
||||
_current_buttons_container = _multiple_items_container
|
||||
|
||||
|
||||
func _set_item_details(item: TreeItem) -> void:
|
||||
if not item.has_meta("node"):
|
||||
return
|
||||
var data = item.get_meta("node")
|
||||
_single_item_container.set_resource_details(data)
|
||||
|
||||
|
||||
func _on_multiple_items_import_triggered():
|
||||
var selected_item = _resource_tree.get_next_selected(null)
|
||||
var all_resources = []
|
||||
var scenes_to_open = 0
|
||||
|
||||
while selected_item != null:
|
||||
scenes_to_open += _set_all_resources(selected_item.get_meta("node"), all_resources)
|
||||
selected_item = _resource_tree.get_next_selected(selected_item)
|
||||
|
||||
_resources_to_process = all_resources
|
||||
_show_confirmation_message(scenes_to_open, all_resources.size())
|
||||
|
||||
|
||||
func _on_single_item_import_triggered():
|
||||
var selected = _resource_tree.get_selected()
|
||||
var meta = selected.get_meta("node")
|
||||
|
||||
if meta.type == "resource":
|
||||
await _trigger_import(_resource_tree.get_selected().get_meta("node"))
|
||||
_set_tree_item_as_saved(_resource_tree.get_selected())
|
||||
_single_item_container.hide_source_change_warning()
|
||||
EditorInterface.save_scene()
|
||||
else:
|
||||
var selected_item = _resource_tree.get_selected()
|
||||
var all_resources = []
|
||||
var scenes_to_open = _set_all_resources(selected_item.get_meta("node"), all_resources)
|
||||
_resources_to_process = all_resources
|
||||
_show_confirmation_message(scenes_to_open, all_resources.size())
|
||||
|
||||
|
||||
func _on_single_item_open_scene_triggered():
|
||||
var selected_item = _resource_tree.get_selected()
|
||||
var meta = selected_item.get_meta("node")
|
||||
if meta.type == "file":
|
||||
EditorInterface.open_scene_from_path(meta.path)
|
||||
else:
|
||||
EditorInterface.open_scene_from_path(meta.scene_path)
|
||||
|
||||
|
||||
func _set_all_resources(meta: Dictionary, resources: Array):
|
||||
var scenes_to_open = 0
|
||||
match meta.type:
|
||||
"dir":
|
||||
for c in meta.children:
|
||||
scenes_to_open += _set_all_resources(c, resources)
|
||||
"file":
|
||||
scenes_to_open += 1
|
||||
for r in meta.resources:
|
||||
if not resources.has(r):
|
||||
resources.push_back(r)
|
||||
"resource":
|
||||
if not resources.has(meta):
|
||||
resources.push_back(meta)
|
||||
return scenes_to_open
|
||||
|
||||
|
||||
func _save_all_scenes():
|
||||
EditorInterface.save_all_scenes()
|
||||
_reload_tree()
|
||||
|
||||
|
||||
func _show_confirmation_message(scenes: int, resources: int):
|
||||
_current_buttons_container.hide_buttons()
|
||||
if scenes > 1:
|
||||
_confirmation_warning_container.set_message("You are about to open %s scenes and re-import %s resources. Do you wish to continue?" % [scenes, resources])
|
||||
else:
|
||||
_confirmation_warning_container.set_message("You are about to re-import %s resources. Do you wish to continue?" % resources)
|
||||
|
||||
_confirmation_warning_container.show()
|
||||
|
||||
|
||||
func _on_resource_tree_refresh_triggered():
|
||||
_set_empty_details_state()
|
||||
_reload_tree()
|
||||
|
||||
|
||||
func _reload_tree():
|
||||
_confirmation_warning_container.hide()
|
||||
_resources_to_process = null
|
||||
if _current_buttons_container != null:
|
||||
_current_buttons_container.show_buttons()
|
||||
_current_buttons_container = null
|
||||
|
||||
_selection_count = 0
|
||||
_resource_tree.clear()
|
||||
var file_tree = _get_file_tree("res://")
|
||||
_setup_tree(file_tree)
|
||||
|
||||
|
||||
func _set_empty_details_state():
|
||||
_nothing_container.show()
|
||||
_single_item_container.hide()
|
||||
_multiple_items_container.hide()
|
||||
_confirmation_warning_container.hide()
|
||||
|
||||
|
||||
func _set_tree_item_as_saved(item: TreeItem) -> void:
|
||||
var meta = item.get_meta("node")
|
||||
meta.has_changes = false
|
||||
item.set_meta("node", meta)
|
||||
item.set_text(0, meta.name)
|
||||
|
||||
|
||||
func _on_confirmation_warning_warning_confirmed():
|
||||
_confirmation_warning_container.hide()
|
||||
_current_buttons_container.show_buttons()
|
||||
|
||||
for resource in _resources_to_process:
|
||||
await _trigger_import(resource)
|
||||
EditorInterface.mark_scene_as_unsaved()
|
||||
_resources_to_process = null
|
||||
|
||||
_should_save_in = 1
|
||||
|
||||
|
||||
func _on_confirmation_warning_warning_declined():
|
||||
_confirmation_warning_container.hide()
|
||||
_current_buttons_container.show_buttons()
|
||||
_resources_to_process = null
|
||||
@@ -0,0 +1,87 @@
|
||||
[gd_scene load_steps=7 format=3 uid="uid://ci67r2f2btg5"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/imports_manager/dock_imports_panel.gd" id="1_1xyeb"]
|
||||
[ext_resource type="PackedScene" uid="uid://cisgsfvp4nf1g" path="res://addons/AsepriteWizard/interface/shared/tree/resource_tree.tscn" id="2_d1s4o"]
|
||||
[ext_resource type="PackedScene" uid="uid://qgmln507kjnm" path="res://addons/AsepriteWizard/interface/shared/tree/tree_selection_confirmation_warning.tscn" id="3_2us73"]
|
||||
[ext_resource type="PackedScene" uid="uid://dnlk2yep7teea" path="res://addons/AsepriteWizard/interface/imports_manager/tree_selection_single_item.tscn" id="3_4ufqa"]
|
||||
[ext_resource type="PackedScene" uid="uid://bhtu6mlwmthqo" path="res://addons/AsepriteWizard/interface/imports_manager/tree_selection_multiple_items.tscn" id="3_pw8ds"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_edrvq"]
|
||||
|
||||
[node name="dock_imports" type="Panel"]
|
||||
custom_minimum_size = Vector2(600, 400)
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_styles/panel = SubResource("StyleBoxEmpty_edrvq")
|
||||
script = ExtResource("1_1xyeb")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
custom_minimum_size = Vector2(400, 300)
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HSplitContainer" type="HSplitContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="tree" parent="MarginContainer/VBoxContainer/HSplitContainer" instance=ExtResource("2_d1s4o")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/HSplitContainer"]
|
||||
custom_minimum_size = Vector2(200, 0)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
text = "Details"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="nothing" type="Label" parent="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 6
|
||||
text = "Nothing selected"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="single_item" parent="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer" instance=ExtResource("3_4ufqa")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="multiple_items" parent="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer" instance=ExtResource("3_pw8ds")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="confirmation_warning" parent="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer" instance=ExtResource("3_2us73")]
|
||||
layout_mode = 2
|
||||
|
||||
[connection signal="multi_selected" from="MarginContainer/VBoxContainer/HSplitContainer/tree" to="." method="_on_resource_tree_multi_selected"]
|
||||
[connection signal="refresh_triggered" from="MarginContainer/VBoxContainer/HSplitContainer/tree" to="." method="_on_resource_tree_refresh_triggered"]
|
||||
[connection signal="import_triggered" from="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/single_item" to="." method="_on_single_item_import_triggered"]
|
||||
[connection signal="open_scene_triggered" from="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/single_item" to="." method="_on_single_item_open_scene_triggered"]
|
||||
[connection signal="import_triggered" from="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/multiple_items" to="." method="_on_multiple_items_import_triggered"]
|
||||
[connection signal="warning_confirmed" from="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/confirmation_warning" to="." method="_on_confirmation_warning_warning_confirmed"]
|
||||
[connection signal="warning_declined" from="MarginContainer/VBoxContainer/HSplitContainer/MarginContainer/VBoxContainer/confirmation_warning" to="." method="_on_confirmation_warning_warning_declined"]
|
||||
123
addons/AsepriteWizard/interface/imports_manager/import_helper.gd
Normal file
123
addons/AsepriteWizard/interface/imports_manager/import_helper.gd
Normal file
@@ -0,0 +1,123 @@
|
||||
@tool
|
||||
extends RefCounted
|
||||
|
||||
const wizard_config = preload("../../config/wizard_config.gd")
|
||||
const result_code = preload("../../config/result_codes.gd")
|
||||
|
||||
var _sprite_animation_creator = preload("../../creators/animation_player/sprite_animation_creator.gd").new()
|
||||
var _texture_rect_animation_creator = preload("../../creators/animation_player/texture_rect_animation_creator.gd").new()
|
||||
var _static_texture_creator = preload("../../creators/static_texture/texture_creator.gd").new()
|
||||
var _sprite_frames_creator = preload("../../creators/sprite_frames/sprite_frames_creator.gd").new()
|
||||
var _aseprite_file_exporter = preload("../../aseprite/file_exporter.gd").new()
|
||||
var _config = preload("../../config/config.gd").new()
|
||||
|
||||
|
||||
func import_node(root_node: Node, meta: Dictionary) -> void:
|
||||
var node = root_node.get_node(meta.node_path)
|
||||
|
||||
if node == null:
|
||||
printerr("Node not found: %s" % meta.node_path)
|
||||
return
|
||||
|
||||
if node is AnimatedSprite2D or node is AnimatedSprite3D:
|
||||
await _sprite_frames_import(node, meta)
|
||||
else:
|
||||
await _animation_import(node, root_node, meta)
|
||||
|
||||
|
||||
func _sprite_frames_import(node: Node, resource_config: Dictionary) -> void:
|
||||
var config = resource_config.meta
|
||||
if not config.source:
|
||||
printerr("Node config missing information.")
|
||||
return
|
||||
|
||||
var source = ProjectSettings.globalize_path(config.source)
|
||||
var options = _parse_import_options(config, resource_config.scene_path.get_base_dir())
|
||||
|
||||
var aseprite_output = _aseprite_file_exporter.generate_aseprite_file(source, options)
|
||||
|
||||
if not aseprite_output.is_ok:
|
||||
printerr(result_code.get_error_message(aseprite_output.code))
|
||||
return
|
||||
|
||||
EditorInterface.get_resource_filesystem().scan()
|
||||
|
||||
await EditorInterface.get_resource_filesystem().filesystem_changed
|
||||
|
||||
_sprite_frames_creator.create_animations(node, aseprite_output.content, { "slice": options.slice })
|
||||
|
||||
wizard_config.set_source_hash(node, FileAccess.get_md5(source))
|
||||
_handle_cleanup(aseprite_output.content)
|
||||
|
||||
|
||||
func _animation_import(node: Node, root_node: Node, resource_config: Dictionary) -> void:
|
||||
if not resource_config.meta.source:
|
||||
printerr("Node config missing information.")
|
||||
return
|
||||
|
||||
if resource_config.meta.get("i_mode", 0) == 0:
|
||||
await _import_to_animation_player(node, root_node, resource_config)
|
||||
else:
|
||||
await _import_static(node, resource_config)
|
||||
|
||||
|
||||
func _import_to_animation_player(node: Node, root: Node, resource_config: Dictionary) -> void:
|
||||
var config = resource_config.meta
|
||||
var source = ProjectSettings.globalize_path(config.source)
|
||||
var options = _parse_import_options(config, resource_config.scene_path.get_base_dir())
|
||||
|
||||
var aseprite_output = _aseprite_file_exporter.generate_aseprite_file(source, options)
|
||||
if not aseprite_output.is_ok:
|
||||
printerr(result_code.get_error_message(aseprite_output.code))
|
||||
return
|
||||
|
||||
EditorInterface.get_resource_filesystem().scan()
|
||||
await EditorInterface.get_resource_filesystem().filesystem_changed
|
||||
|
||||
var anim_options = {
|
||||
"keep_anim_length": config.keep_anim_length,
|
||||
"cleanup_hide_unused_nodes": config.get("set_vis_track"),
|
||||
"slice": config.get("slice", ""),
|
||||
}
|
||||
var animation_creator = _texture_rect_animation_creator if node is TextureRect else _sprite_animation_creator
|
||||
animation_creator.create_animations(node, root.get_node(config.player), aseprite_output.content, anim_options)
|
||||
|
||||
wizard_config.set_source_hash(node, FileAccess.get_md5(source))
|
||||
_handle_cleanup(aseprite_output.content)
|
||||
|
||||
|
||||
func _import_static(node: Node, resource_config: Dictionary) -> void:
|
||||
var config = resource_config.meta
|
||||
var source = ProjectSettings.globalize_path(config.source)
|
||||
var options = _parse_import_options(config, resource_config.scene_path.get_base_dir())
|
||||
options["first_frame_only"] = true
|
||||
|
||||
var aseprite_output = _aseprite_file_exporter.generate_aseprite_file(source, options)
|
||||
|
||||
if not aseprite_output.is_ok:
|
||||
printerr(result_code.get_error_message(aseprite_output.code))
|
||||
return
|
||||
|
||||
EditorInterface.get_resource_filesystem().scan()
|
||||
await EditorInterface.get_resource_filesystem().filesystem_changed
|
||||
|
||||
_static_texture_creator.load_texture(node, aseprite_output.content, { "slice": options.slice })
|
||||
|
||||
wizard_config.set_source_hash(node, FileAccess.get_md5(source))
|
||||
_handle_cleanup(aseprite_output.content)
|
||||
|
||||
|
||||
func _parse_import_options(config: Dictionary, scene_base_path: String) -> Dictionary:
|
||||
return {
|
||||
"output_folder": config.o_folder if config.o_folder != "" else scene_base_path,
|
||||
"exception_pattern": config.o_ex_p,
|
||||
"only_visible_layers": config.only_visible,
|
||||
"output_filename": config.o_name,
|
||||
"layer": config.get("layer"),
|
||||
"slice": config.get("slice", ""),
|
||||
}
|
||||
|
||||
func _handle_cleanup(aseprite_content):
|
||||
if _config.should_remove_source_files():
|
||||
DirAccess.remove_absolute(aseprite_content.data_file)
|
||||
EditorInterface.get_resource_filesystem().scan()
|
||||
@@ -0,0 +1,28 @@
|
||||
@tool
|
||||
extends MarginContainer
|
||||
|
||||
signal dock_requested
|
||||
|
||||
enum Tabs {
|
||||
DOCK_IMPORTS = 0,
|
||||
}
|
||||
|
||||
@onready var _tabs: TabContainer = $TabContainer
|
||||
@onready var _dock_button: Button = $dock_button
|
||||
|
||||
func _ready():
|
||||
_tabs.set_tab_title(Tabs.DOCK_IMPORTS, "Dock Imports")
|
||||
_dock_button.icon = get_theme_icon("MakeFloating", "EditorIcons")
|
||||
set_as_floating()
|
||||
|
||||
|
||||
func _on_dock_button_pressed():
|
||||
dock_requested.emit()
|
||||
|
||||
|
||||
func set_as_floating():
|
||||
_dock_button.tooltip_text = "Dock window"
|
||||
|
||||
|
||||
func set_as_docked():
|
||||
_dock_button.tooltip_text = "Undock window"
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,22 @@
|
||||
@tool
|
||||
extends LineEdit
|
||||
|
||||
signal change_finished(text: String)
|
||||
|
||||
@export var debounce_time_in_seconds: float = 0.3
|
||||
|
||||
var _time_since_last_change: float = 0.0
|
||||
var _has_pending_changes: bool = false
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if _has_pending_changes:
|
||||
_time_since_last_change += delta
|
||||
if _time_since_last_change > debounce_time_in_seconds:
|
||||
_has_pending_changes = false
|
||||
change_finished.emit(self.text)
|
||||
|
||||
|
||||
func _on_text_changed(_new_text: String) -> void:
|
||||
_has_pending_changes = true
|
||||
_time_since_last_change = 0
|
||||
@@ -0,0 +1,22 @@
|
||||
@tool
|
||||
extends VBoxContainer
|
||||
|
||||
signal import_triggered
|
||||
|
||||
@onready var _import_message = $message
|
||||
@onready var _import_button = $buttons
|
||||
|
||||
func set_selected_count(number_of_items: int) -> void:
|
||||
_import_message.text = "%2d items selected" % number_of_items
|
||||
|
||||
|
||||
func show_buttons():
|
||||
_import_button.show()
|
||||
|
||||
|
||||
func hide_buttons():
|
||||
_import_button.hide()
|
||||
|
||||
|
||||
func _on_import_selected_button_up():
|
||||
import_triggered.emit()
|
||||
@@ -0,0 +1,25 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bhtu6mlwmthqo"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/imports_manager/tree_selection_multiple_items.gd" id="1_beamo"]
|
||||
|
||||
[node name="multiple_items" type="VBoxContainer"]
|
||||
visible = false
|
||||
size_flags_vertical = 3
|
||||
script = ExtResource("1_beamo")
|
||||
|
||||
[node name="message" type="Label" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 6
|
||||
text = "Multiple items selected
|
||||
"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="buttons" type="HFlowContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="import_selected" type="Button" parent="buttons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Re-Import all"
|
||||
|
||||
[connection signal="button_up" from="buttons/import_selected" to="." method="_on_import_selected_button_up"]
|
||||
@@ -0,0 +1,141 @@
|
||||
@tool
|
||||
extends VBoxContainer
|
||||
|
||||
signal import_triggered
|
||||
signal open_scene_triggered
|
||||
|
||||
@onready var _name = $GridContainer/name_value
|
||||
@onready var _type = $GridContainer/type_value
|
||||
@onready var _path = $GridContainer/path_value
|
||||
|
||||
@onready var _source_label = $GridContainer/source_file_label
|
||||
@onready var _source = $GridContainer/source_file_value
|
||||
@onready var _layer_label = $GridContainer/layer_label
|
||||
@onready var _layer = $GridContainer/layer_value
|
||||
@onready var _slice_label = $GridContainer/slice_label
|
||||
@onready var _slice = $GridContainer/slice_value
|
||||
|
||||
@onready var _o_name_label = $GridContainer/o_name_label
|
||||
@onready var _o_name = $GridContainer/o_name_value
|
||||
@onready var _o_folder_label = $GridContainer/o_folder_label
|
||||
@onready var _o_folder_value = $GridContainer/o_folder_value
|
||||
|
||||
|
||||
@onready var _resource_buttons = $resource_buttons
|
||||
@onready var _dir_buttons = $dir_buttons
|
||||
@onready var _scene_buttons = $scene_buttons
|
||||
|
||||
@onready var _source_change_warning = $source_changed_warning
|
||||
|
||||
@onready var _resource_only_fields = [
|
||||
_source_label,
|
||||
_source,
|
||||
_layer_label,
|
||||
_layer,
|
||||
_slice_label,
|
||||
_slice,
|
||||
_o_name_label,
|
||||
_o_name,
|
||||
_o_folder_label,
|
||||
_o_folder_value,
|
||||
_source_change_warning,
|
||||
]
|
||||
|
||||
var _current_resource_type = "resource"
|
||||
var _resource_config: Dictionary = {}
|
||||
|
||||
func _ready():
|
||||
_source_change_warning.set_text("Source file changed since last import")
|
||||
_source_change_warning.hide()
|
||||
|
||||
|
||||
func set_resource_details(resource_details: Dictionary) -> void:
|
||||
_resource_config = resource_details
|
||||
_resource_buttons.hide()
|
||||
_dir_buttons.hide()
|
||||
_scene_buttons.hide()
|
||||
_source_change_warning.hide()
|
||||
|
||||
_current_resource_type = resource_details.type
|
||||
match resource_details.type:
|
||||
"dir":
|
||||
_name.text = resource_details.name
|
||||
_type.text = "Folder"
|
||||
_path.text = resource_details.path
|
||||
_hide_resource_fields()
|
||||
_dir_buttons.show()
|
||||
"file":
|
||||
_name.text = resource_details.name
|
||||
_type.text = "File"
|
||||
_path.text = resource_details.path
|
||||
_hide_resource_fields()
|
||||
_scene_buttons.show()
|
||||
"resource":
|
||||
_name.text = resource_details.node_name
|
||||
_type.text = resource_details.node_type
|
||||
_path.text = resource_details.node_path
|
||||
|
||||
var meta = resource_details.meta
|
||||
_source.text = meta.source
|
||||
_layer.text = "All" if meta.get("layer", "") == "" else meta.layer
|
||||
_slice.text = "All" if meta.get("slice", "") == "" else meta.slice
|
||||
|
||||
var folder = resource_details.scene_path.get_base_dir() if meta.get("o_folder", "") == "" else meta.o_folder
|
||||
var file_name = "" if meta.get("o_name", "") == "" else meta.o_name
|
||||
|
||||
if _layer.text != "All":
|
||||
file_name += _layer.text
|
||||
elif file_name == "":
|
||||
file_name = meta.source.get_basename().get_file()
|
||||
_o_name.text = "%s/%s.png" % [folder, file_name]
|
||||
|
||||
_show_resource_fields()
|
||||
_resource_buttons.show()
|
||||
|
||||
_source_change_warning.visible = resource_details.has_changes
|
||||
|
||||
|
||||
func _hide_resource_fields():
|
||||
for f in _resource_only_fields:
|
||||
f.hide()
|
||||
|
||||
|
||||
func _show_resource_fields():
|
||||
for f in _resource_only_fields:
|
||||
f.show()
|
||||
|
||||
|
||||
func show_buttons():
|
||||
match _current_resource_type:
|
||||
"resource":
|
||||
_resource_buttons.show()
|
||||
"scene":
|
||||
_scene_buttons.show()
|
||||
_:
|
||||
_dir_buttons.show()
|
||||
|
||||
|
||||
func hide_buttons():
|
||||
_resource_buttons.hide()
|
||||
_dir_buttons.hide()
|
||||
_scene_buttons.hide()
|
||||
|
||||
|
||||
func hide_source_change_warning():
|
||||
_source_change_warning.hide()
|
||||
|
||||
|
||||
func _on_show_dir_in_fs_button_up():
|
||||
EditorInterface.get_file_system_dock().navigate_to_path(_path.text)
|
||||
|
||||
|
||||
func _on_import_all_button_up():
|
||||
import_triggered.emit()
|
||||
|
||||
|
||||
func _on_import_button_up():
|
||||
import_triggered.emit()
|
||||
|
||||
|
||||
func _on_open_scene_button_up():
|
||||
open_scene_triggered.emit()
|
||||
@@ -0,0 +1,158 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dnlk2yep7teea"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/AsepriteWizard/interface/imports_manager/tree_selection_single_item.gd" id="1_bb3ui"]
|
||||
[ext_resource type="PackedScene" uid="uid://c1l0bk12iwln3" path="res://addons/AsepriteWizard/interface/shared/tree/inline_warning_panel.tscn" id="2_weuqf"]
|
||||
|
||||
[node name="single_item" type="VBoxContainer"]
|
||||
visible = false
|
||||
script = ExtResource("1_bb3ui")
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/h_separation = 10
|
||||
columns = 2
|
||||
|
||||
[node name="type_label" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
text = "Type"
|
||||
|
||||
[node name="type_value" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
text = "-"
|
||||
|
||||
[node name="name_label" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
text = "Name"
|
||||
|
||||
[node name="name_value" type="Label" parent="GridContainer"]
|
||||
custom_minimum_size = Vector2(50, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "-"
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="path_label" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
text = "Path"
|
||||
|
||||
[node name="path_value" type="Label" parent="GridContainer"]
|
||||
custom_minimum_size = Vector2(50, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "-"
|
||||
autowrap_mode = 1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="source_file_label" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
text = "Aseprite File"
|
||||
|
||||
[node name="source_file_value" type="Label" parent="GridContainer"]
|
||||
custom_minimum_size = Vector2(50, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "-"
|
||||
autowrap_mode = 1
|
||||
|
||||
[node name="layer_label" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
text = "Layer"
|
||||
|
||||
[node name="layer_value" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
text = "-"
|
||||
|
||||
[node name="slice_label" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
text = "Slice"
|
||||
|
||||
[node name="slice_value" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
text = "-"
|
||||
|
||||
[node name="o_folder_label" type="Label" parent="GridContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
text = "Output folder"
|
||||
|
||||
[node name="o_folder_value" type="Label" parent="GridContainer"]
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(50, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "-"
|
||||
|
||||
[node name="o_name_label" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
text = "Spritesheet name"
|
||||
|
||||
[node name="o_name_value" type="Label" parent="GridContainer"]
|
||||
layout_mode = 2
|
||||
text = "-"
|
||||
|
||||
[node name="source_changed_warning" parent="." instance=ExtResource("2_weuqf")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="resource_buttons" type="HFlowContainer" parent="."]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="import" type="Button" parent="resource_buttons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Re-Import"
|
||||
|
||||
[node name="open_scene" type="Button" parent="resource_buttons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Open Scene"
|
||||
|
||||
[node name="scene_buttons" type="HFlowContainer" parent="."]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="import_all" type="Button" parent="scene_buttons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Re-Import all"
|
||||
|
||||
[node name="open_scene" type="Button" parent="scene_buttons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Open Scene"
|
||||
|
||||
[node name="dir_buttons" type="HFlowContainer" parent="."]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="import_all" type="Button" parent="dir_buttons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Re-Import all"
|
||||
|
||||
[node name="show_dir_in_fs" type="Button" parent="dir_buttons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Show In FileSystem"
|
||||
|
||||
[connection signal="button_up" from="resource_buttons/import" to="." method="_on_import_button_up"]
|
||||
[connection signal="button_up" from="resource_buttons/open_scene" to="." method="_on_open_scene_button_up"]
|
||||
[connection signal="button_up" from="scene_buttons/import_all" to="." method="_on_import_all_button_up"]
|
||||
[connection signal="button_up" from="scene_buttons/open_scene" to="." method="_on_open_scene_button_up"]
|
||||
[connection signal="button_up" from="dir_buttons/import_all" to="." method="_on_import_all_button_up"]
|
||||
[connection signal="button_up" from="dir_buttons/show_dir_in_fs" to="." method="_on_show_dir_in_fs_button_up"]
|
||||
Reference in New Issue
Block a user