parent
6c3be182aa
commit
0b603c75ca
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,7 +14,6 @@ Thumbs.db
|
|||||||
*.lnk
|
*.lnk
|
||||||
# Godot-specific ignores
|
# Godot-specific ignores
|
||||||
.import/
|
.import/
|
||||||
.addons/
|
|
||||||
export.cfg
|
export.cfg
|
||||||
export_presets.cfg
|
export_presets.cfg
|
||||||
|
|
||||||
|
|||||||
@ -1,239 +0,0 @@
|
|||||||
[gd_scene load_steps=2 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/AsepriteWizard/animated_sprite/sf_wizard_dock.gd" type="Script" id=1]
|
|
||||||
|
|
||||||
[node name="ASWizardWindow" type="PanelContainer"]
|
|
||||||
margin_right = 600.0
|
|
||||||
margin_bottom = 600.0
|
|
||||||
rect_min_size = Vector2( 600, 600 )
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_vertical = 0
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="container" type="MarginContainer" parent="."]
|
|
||||||
margin_left = 7.0
|
|
||||||
margin_top = 7.0
|
|
||||||
margin_right = 593.0
|
|
||||||
margin_bottom = 593.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_vertical = 3
|
|
||||||
custom_constants/margin_right = 30
|
|
||||||
custom_constants/margin_top = 30
|
|
||||||
custom_constants/margin_left = 30
|
|
||||||
custom_constants/margin_bottom = 30
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="options" type="VBoxContainer" parent="container"]
|
|
||||||
margin_left = 30.0
|
|
||||||
margin_top = 30.0
|
|
||||||
margin_right = 556.0
|
|
||||||
margin_bottom = 556.0
|
|
||||||
custom_constants/separation = 20
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="file_location" type="VBoxContainer" parent="container/options"]
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
custom_constants/separation = 10
|
|
||||||
|
|
||||||
[node name="file_location_label" type="Label" parent="container/options/file_location"]
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
hint_tooltip = "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"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
custom_constants/separation = 20
|
|
||||||
|
|
||||||
[node name="file_location_path" type="LineEdit" parent="container/options/file_location/HBoxContainer"]
|
|
||||||
margin_right = 431.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
caret_blink = true
|
|
||||||
|
|
||||||
[node name="file_location_btn" type="Button" parent="container/options/file_location/HBoxContainer"]
|
|
||||||
margin_left = 451.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
text = "Select file"
|
|
||||||
|
|
||||||
[node name="output_folder" type="VBoxContainer" parent="container/options"]
|
|
||||||
margin_top = 68.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 116.0
|
|
||||||
custom_constants/separation = 10
|
|
||||||
|
|
||||||
[node name="label" type="Label" parent="container/options/output_folder"]
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
hint_tooltip = "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"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
custom_constants/separation = 20
|
|
||||||
|
|
||||||
[node name="file_location_path" type="LineEdit" parent="container/options/output_folder/HBoxContainer"]
|
|
||||||
margin_right = 431.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
text = "res://"
|
|
||||||
caret_blink = true
|
|
||||||
|
|
||||||
[node name="output_folder_btn" type="Button" parent="container/options/output_folder/HBoxContainer"]
|
|
||||||
margin_left = 451.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
text = "Select file"
|
|
||||||
|
|
||||||
[node name="exclude_pattern" type="VBoxContainer" parent="container/options"]
|
|
||||||
margin_top = 136.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 184.0
|
|
||||||
custom_constants/separation = 10
|
|
||||||
|
|
||||||
[node name="label" type="Label" parent="container/options/exclude_pattern"]
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
hint_tooltip = "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"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
caret_blink = true
|
|
||||||
|
|
||||||
[node name="custom_filename" type="VBoxContainer" parent="container/options"]
|
|
||||||
margin_top = 204.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 252.0
|
|
||||||
custom_constants/separation = 10
|
|
||||||
|
|
||||||
[node name="label" type="Label" parent="container/options/custom_filename"]
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
hint_tooltip = "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"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
caret_blink = true
|
|
||||||
|
|
||||||
[node name="layer_importing_mode" type="VBoxContainer" parent="container/options"]
|
|
||||||
margin_top = 272.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 388.0
|
|
||||||
custom_constants/separation = 10
|
|
||||||
|
|
||||||
[node name="label" type="Label" parent="container/options/layer_importing_mode"]
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
mouse_filter = 1
|
|
||||||
text = "Options:"
|
|
||||||
|
|
||||||
[node name="split_layers" type="HBoxContainer" parent="container/options/layer_importing_mode"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
hint_tooltip = "If selected, one resource will be created for each layer.
|
|
||||||
If not selected, layers will be merged and exported as one SpriteSheet."
|
|
||||||
|
|
||||||
[node name="label" type="Label" parent="container/options/layer_importing_mode/split_layers"]
|
|
||||||
margin_top = 5.0
|
|
||||||
margin_right = 250.0
|
|
||||||
margin_bottom = 19.0
|
|
||||||
rect_min_size = Vector2( 250, 0 )
|
|
||||||
mouse_filter = 1
|
|
||||||
text = "Split layers in multiple resources"
|
|
||||||
|
|
||||||
[node name="field" type="CheckBox" parent="container/options/layer_importing_mode/split_layers"]
|
|
||||||
margin_left = 254.0
|
|
||||||
margin_right = 301.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
text = "On"
|
|
||||||
|
|
||||||
[node name="visible_layers" type="HBoxContainer" parent="container/options/layer_importing_mode"]
|
|
||||||
margin_top = 58.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 82.0
|
|
||||||
hint_tooltip = "If selected, layers not visible in the source file won't be included in the final image."
|
|
||||||
|
|
||||||
[node name="label" type="Label" parent="container/options/layer_importing_mode/visible_layers"]
|
|
||||||
margin_top = 5.0
|
|
||||||
margin_right = 250.0
|
|
||||||
margin_bottom = 19.0
|
|
||||||
rect_min_size = Vector2( 250, 0 )
|
|
||||||
text = "Only include visible layers"
|
|
||||||
|
|
||||||
[node name="field" type="CheckBox" parent="container/options/layer_importing_mode/visible_layers"]
|
|
||||||
margin_left = 254.0
|
|
||||||
margin_right = 301.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
text = "On"
|
|
||||||
|
|
||||||
[node name="disable_resource_creation" type="HBoxContainer" parent="container/options/layer_importing_mode"]
|
|
||||||
margin_top = 92.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 116.0
|
|
||||||
hint_tooltip = "Does not create SpriteFrames resource. Useful if you are only interested in the .json and .png output from Aseprite."
|
|
||||||
|
|
||||||
[node name="label" type="Label" parent="container/options/layer_importing_mode/disable_resource_creation"]
|
|
||||||
margin_top = 5.0
|
|
||||||
margin_right = 250.0
|
|
||||||
margin_bottom = 19.0
|
|
||||||
rect_min_size = Vector2( 250, 0 )
|
|
||||||
text = "Do not create resource file"
|
|
||||||
|
|
||||||
[node name="field" type="CheckBox" parent="container/options/layer_importing_mode/disable_resource_creation"]
|
|
||||||
margin_left = 254.0
|
|
||||||
margin_right = 301.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
text = "On"
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_description_": "Only source *.json and *.png files will be created."
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="buttons" type="HBoxContainer" parent="container/options"]
|
|
||||||
margin_top = 408.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 428.0
|
|
||||||
custom_constants/separation = 30
|
|
||||||
alignment = 2
|
|
||||||
|
|
||||||
[node name="close" type="Button" parent="container/options/buttons"]
|
|
||||||
margin_left = 393.0
|
|
||||||
margin_right = 440.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
text = "Close"
|
|
||||||
|
|
||||||
[node name="next" type="Button" parent="container/options/buttons"]
|
|
||||||
margin_left = 470.0
|
|
||||||
margin_right = 526.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
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"]
|
|
||||||
@ -1,206 +0,0 @@
|
|||||||
tool
|
|
||||||
extends PanelContainer
|
|
||||||
|
|
||||||
const wizard_config = preload("../config/wizard_config.gd")
|
|
||||||
const result_code = preload("../config/result_codes.gd")
|
|
||||||
var sprite_frames_creator = preload("sprite_frames_creator.gd").new()
|
|
||||||
|
|
||||||
var scene: Node
|
|
||||||
var sprite: AnimatedSprite
|
|
||||||
|
|
||||||
var config
|
|
||||||
var file_system: EditorFileSystem
|
|
||||||
|
|
||||||
var _layer: String = ""
|
|
||||||
var _source: String = ""
|
|
||||||
var _file_dialog_aseprite: FileDialog
|
|
||||||
var _output_folder_dialog: FileDialog
|
|
||||||
var _importing := false
|
|
||||||
|
|
||||||
var _output_folder := ""
|
|
||||||
var _out_folder_default := "[Same as scene]"
|
|
||||||
var _layer_default := "[all]"
|
|
||||||
|
|
||||||
onready var _source_field = $margin/VBoxContainer/source/button
|
|
||||||
onready var _layer_field = $margin/VBoxContainer/layer/options
|
|
||||||
onready var _options_title = $margin/VBoxContainer/options_title/options_title
|
|
||||||
onready var _options_container = $margin/VBoxContainer/options
|
|
||||||
onready var _out_folder_field = $margin/VBoxContainer/options/out_folder/button
|
|
||||||
onready var _out_filename_field = $margin/VBoxContainer/options/out_filename/LineEdit
|
|
||||||
onready var _visible_layers_field = $margin/VBoxContainer/options/visible_layers/CheckButton
|
|
||||||
onready var _ex_pattern_field = $margin/VBoxContainer/options/ex_pattern/LineEdit
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
var cfg = wizard_config.decode(sprite.editor_description)
|
|
||||||
|
|
||||||
if cfg == null:
|
|
||||||
_load_default_config()
|
|
||||||
else:
|
|
||||||
_load_config(cfg)
|
|
||||||
|
|
||||||
sprite_frames_creator.init(config, file_system)
|
|
||||||
|
|
||||||
|
|
||||||
func _load_config(cfg):
|
|
||||||
if cfg.has("source"):
|
|
||||||
_set_source(cfg.source)
|
|
||||||
|
|
||||||
if cfg.get("layer", "") != "":
|
|
||||||
_set_layer(cfg.layer)
|
|
||||||
|
|
||||||
_output_folder = cfg.get("o_folder", "")
|
|
||||||
_out_folder_field.text = _output_folder if _output_folder != "" else _out_folder_default
|
|
||||||
_out_filename_field.text = cfg.get("o_name", "")
|
|
||||||
_visible_layers_field.pressed = cfg.get("only_visible", "") == "True"
|
|
||||||
_ex_pattern_field.text = cfg.get("o_ex_p", "")
|
|
||||||
|
|
||||||
_set_options_visible(cfg.get("op_exp", "false") == "True")
|
|
||||||
|
|
||||||
|
|
||||||
func _load_default_config():
|
|
||||||
_ex_pattern_field.text = config.get_default_exclusion_pattern()
|
|
||||||
_set_options_visible(false)
|
|
||||||
|
|
||||||
|
|
||||||
func _set_source(source):
|
|
||||||
_source = source
|
|
||||||
_source_field.text = _source
|
|
||||||
_source_field.hint_tooltip = _source
|
|
||||||
|
|
||||||
|
|
||||||
func _set_layer(layer):
|
|
||||||
_layer = layer
|
|
||||||
_layer_field.add_item(_layer)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_layer_pressed():
|
|
||||||
if _source == "":
|
|
||||||
_show_message("Please. Select source file first.")
|
|
||||||
return
|
|
||||||
|
|
||||||
var layers = sprite_frames_creator.list_layers(ProjectSettings.globalize_path(_source))
|
|
||||||
var current = 0
|
|
||||||
_layer_field.clear()
|
|
||||||
_layer_field.add_item("[all]")
|
|
||||||
|
|
||||||
for l in layers:
|
|
||||||
if l == "":
|
|
||||||
continue
|
|
||||||
|
|
||||||
_layer_field.add_item(l)
|
|
||||||
if l == _layer:
|
|
||||||
current = _layer_field.get_item_count() - 1
|
|
||||||
_layer_field.select(current)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_layer_item_selected(index):
|
|
||||||
if index == 0:
|
|
||||||
_layer = ""
|
|
||||||
return
|
|
||||||
_layer = _layer_field.get_item_text(index)
|
|
||||||
_save_config()
|
|
||||||
|
|
||||||
|
|
||||||
func _on_source_pressed():
|
|
||||||
_open_source_dialog()
|
|
||||||
|
|
||||||
|
|
||||||
func _on_import_pressed():
|
|
||||||
if _importing:
|
|
||||||
return
|
|
||||||
_importing = true
|
|
||||||
|
|
||||||
var root = get_tree().get_edited_scene_root()
|
|
||||||
|
|
||||||
if _source == "":
|
|
||||||
_show_message("Aseprite file not selected.")
|
|
||||||
_importing = false
|
|
||||||
return
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
"source": ProjectSettings.globalize_path(_source),
|
|
||||||
"output_folder": _output_folder if _output_folder != "" else root.filename.get_base_dir(),
|
|
||||||
"exception_pattern": _ex_pattern_field.text,
|
|
||||||
"only_visible_layers": _visible_layers_field.pressed,
|
|
||||||
"output_filename": _out_filename_field.text,
|
|
||||||
"layer": _layer
|
|
||||||
}
|
|
||||||
|
|
||||||
_save_config()
|
|
||||||
|
|
||||||
sprite_frames_creator.create_animations(sprite, options)
|
|
||||||
_importing = false
|
|
||||||
|
|
||||||
|
|
||||||
func _save_config():
|
|
||||||
sprite.editor_description = wizard_config.encode({
|
|
||||||
"source": _source,
|
|
||||||
"layer": _layer,
|
|
||||||
"op_exp": _options_title.pressed,
|
|
||||||
"o_folder": _output_folder,
|
|
||||||
"o_name": _out_filename_field.text,
|
|
||||||
"only_visible": _visible_layers_field.pressed,
|
|
||||||
"o_ex_p": _ex_pattern_field.text
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
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 = _source.get_base_dir()
|
|
||||||
_file_dialog_aseprite.popup_centered_ratio()
|
|
||||||
|
|
||||||
|
|
||||||
func _create_aseprite_file_selection():
|
|
||||||
var file_dialog = FileDialog.new()
|
|
||||||
file_dialog.mode = FileDialog.MODE_OPEN_FILE
|
|
||||||
file_dialog.access = FileDialog.ACCESS_FILESYSTEM
|
|
||||||
file_dialog.connect("file_selected", self, "_on_aseprite_file_selected")
|
|
||||||
file_dialog.set_filters(PoolStringArray(["*.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 _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", _warning_dialog, "queue_free")
|
|
||||||
|
|
||||||
|
|
||||||
func _on_options_title_toggled(button_pressed):
|
|
||||||
_set_options_visible(button_pressed)
|
|
||||||
_save_config()
|
|
||||||
|
|
||||||
|
|
||||||
func _set_options_visible(is_visible):
|
|
||||||
_options_container.visible = is_visible
|
|
||||||
_options_title.icon = config.get_icon_arrow_down() if is_visible else config.get_icon_arrow_right()
|
|
||||||
|
|
||||||
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 = FileDialog.new()
|
|
||||||
file_dialog.mode = FileDialog.MODE_OPEN_DIR
|
|
||||||
file_dialog.access = FileDialog.ACCESS_RESOURCES
|
|
||||||
file_dialog.connect("dir_selected", self, "_on_output_folder_selected")
|
|
||||||
return file_dialog
|
|
||||||
|
|
||||||
|
|
||||||
func _on_output_folder_selected(path):
|
|
||||||
_output_folder = path
|
|
||||||
_out_folder_field.text = _output_folder if _output_folder != "" else _out_folder_default
|
|
||||||
_output_folder_dialog.queue_free()
|
|
||||||
@ -1,227 +0,0 @@
|
|||||||
[gd_scene load_steps=5 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/AsepriteWizard/animated_sprite/animated_sprite_inspector_dock.gd" type="Script" id=1]
|
|
||||||
|
|
||||||
[sub_resource type="StyleBoxEmpty" id=1]
|
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id=2]
|
|
||||||
content_margin_left = 2.0
|
|
||||||
content_margin_right = 2.0
|
|
||||||
content_margin_top = 1.0
|
|
||||||
content_margin_bottom = 1.0
|
|
||||||
bg_color = Color( 0.25098, 0.270588, 0.32549, 1 )
|
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id=3]
|
|
||||||
content_margin_left = 1.0
|
|
||||||
content_margin_right = 1.0
|
|
||||||
content_margin_top = 1.0
|
|
||||||
content_margin_bottom = 1.0
|
|
||||||
bg_color = Color( 0.2, 0.219608, 0.278431, 1 )
|
|
||||||
|
|
||||||
[node name="animated_sprite_inspector_dock" type="PanelContainer"]
|
|
||||||
margin_right = 14.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
custom_styles/panel = SubResource( 1 )
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false,
|
|
||||||
"_editor_description_": ""
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="margin" type="MarginContainer" parent="."]
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 120.0
|
|
||||||
custom_constants/margin_top = 2
|
|
||||||
custom_constants/margin_bottom = 2
|
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="margin"]
|
|
||||||
margin_top = 2.0
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 118.0
|
|
||||||
|
|
||||||
[node name="section_title" type="PanelContainer" parent="margin/VBoxContainer"]
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 16.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
custom_styles/panel = SubResource( 2 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="title" type="Label" parent="margin/VBoxContainer/section_title"]
|
|
||||||
margin_left = 2.0
|
|
||||||
margin_top = 1.0
|
|
||||||
margin_right = 95.0
|
|
||||||
margin_bottom = 15.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
text = "Aseprite"
|
|
||||||
align = 1
|
|
||||||
|
|
||||||
[node name="source" type="HBoxContainer" parent="margin/VBoxContainer"]
|
|
||||||
margin_top = 20.0
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 40.0
|
|
||||||
hint_tooltip = "Location of the Aseprite (*.ase, *.aseprite) source file."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/source"]
|
|
||||||
margin_top = 3.0
|
|
||||||
margin_right = 81.0
|
|
||||||
margin_bottom = 17.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Aseprite File"
|
|
||||||
|
|
||||||
[node name="button" type="Button" parent="margin/VBoxContainer/source"]
|
|
||||||
margin_left = 85.0
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "[empty]"
|
|
||||||
clip_text = true
|
|
||||||
|
|
||||||
[node name="layer" type="HBoxContainer" parent="margin/VBoxContainer"]
|
|
||||||
margin_top = 44.0
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 64.0
|
|
||||||
hint_tooltip = "Aseprite layer to be used in the animation. By default all layers are included."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/layer"]
|
|
||||||
margin_top = 3.0
|
|
||||||
margin_right = 41.0
|
|
||||||
margin_bottom = 17.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Layer"
|
|
||||||
|
|
||||||
[node name="options" type="OptionButton" parent="margin/VBoxContainer/layer"]
|
|
||||||
margin_left = 45.0
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "[all]"
|
|
||||||
align = 1
|
|
||||||
|
|
||||||
[node name="options_title" type="PanelContainer" parent="margin/VBoxContainer"]
|
|
||||||
margin_top = 68.0
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 92.0
|
|
||||||
custom_styles/panel = SubResource( 3 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="options_title" type="ToolButton" parent="margin/VBoxContainer/options_title"]
|
|
||||||
margin_left = 1.0
|
|
||||||
margin_top = 1.0
|
|
||||||
margin_right = 96.0
|
|
||||||
margin_bottom = 23.0
|
|
||||||
custom_colors/font_color_pressed = Color( 0.8, 0.807843, 0.827451, 1 )
|
|
||||||
toggle_mode = true
|
|
||||||
text = "Options"
|
|
||||||
align = 0
|
|
||||||
|
|
||||||
[node name="options" type="VBoxContainer" parent="margin/VBoxContainer"]
|
|
||||||
visible = false
|
|
||||||
margin_top = 120.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 240.0
|
|
||||||
|
|
||||||
[node name="out_folder" type="HBoxContainer" parent="margin/VBoxContainer/options"]
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
hint_tooltip = "Location where the spritesheet file should be saved."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/options/out_folder"]
|
|
||||||
margin_top = 3.0
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 17.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Output folder"
|
|
||||||
|
|
||||||
[node name="button" type="Button" parent="margin/VBoxContainer/options/out_folder"]
|
|
||||||
margin_left = 101.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "[empty]"
|
|
||||||
clip_text = true
|
|
||||||
|
|
||||||
[node name="out_filename" type="HBoxContainer" parent="margin/VBoxContainer/options"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
hint_tooltip = "Base filename for spritesheet. In case the layer option is used, this works as a prefix to the layer name."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/options/out_filename"]
|
|
||||||
margin_top = 5.0
|
|
||||||
margin_right = 109.0
|
|
||||||
margin_bottom = 19.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Output file name"
|
|
||||||
|
|
||||||
[node name="LineEdit" type="LineEdit" parent="margin/VBoxContainer/options/out_filename"]
|
|
||||||
margin_left = 113.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
|
|
||||||
[node name="ex_pattern" type="HBoxContainer" parent="margin/VBoxContainer/options"]
|
|
||||||
margin_top = 52.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 76.0
|
|
||||||
hint_tooltip = "Exclude layers with name matching this pattern (regex)."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/options/ex_pattern"]
|
|
||||||
margin_top = 5.0
|
|
||||||
margin_right = 99.0
|
|
||||||
margin_bottom = 19.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Exclude pattern"
|
|
||||||
|
|
||||||
[node name="LineEdit" type="LineEdit" parent="margin/VBoxContainer/options/ex_pattern"]
|
|
||||||
margin_left = 103.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
|
|
||||||
[node name="visible_layers" type="HBoxContainer" parent="margin/VBoxContainer/options"]
|
|
||||||
margin_top = 80.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 120.0
|
|
||||||
hint_tooltip = "If active, layers not visible in the source file won't be included in the final image."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/options/visible_layers"]
|
|
||||||
margin_top = 13.0
|
|
||||||
margin_right = 118.0
|
|
||||||
margin_bottom = 27.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Only visible layers"
|
|
||||||
|
|
||||||
[node name="CheckButton" type="CheckButton" parent="margin/VBoxContainer/options/visible_layers"]
|
|
||||||
margin_left = 122.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 40.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
|
|
||||||
[node name="import" type="Button" parent="margin/VBoxContainer"]
|
|
||||||
margin_top = 96.0
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 116.0
|
|
||||||
text = "Import"
|
|
||||||
|
|
||||||
[connection signal="pressed" from="margin/VBoxContainer/source/button" to="." method="_on_source_pressed"]
|
|
||||||
[connection signal="item_selected" from="margin/VBoxContainer/layer/options" to="." method="_on_layer_item_selected"]
|
|
||||||
[connection signal="pressed" from="margin/VBoxContainer/layer/options" to="." method="_on_layer_pressed"]
|
|
||||||
[connection signal="toggled" from="margin/VBoxContainer/options_title/options_title" to="." method="_on_options_title_toggled"]
|
|
||||||
[connection signal="pressed" from="margin/VBoxContainer/options/out_folder/button" to="." method="_on_out_folder_pressed"]
|
|
||||||
[connection signal="pressed" from="margin/VBoxContainer/import" to="." method="_on_import_pressed"]
|
|
||||||
@ -1,233 +0,0 @@
|
|||||||
tool
|
|
||||||
extends EditorImportPlugin
|
|
||||||
|
|
||||||
const result_codes = preload("../config/result_codes.gd")
|
|
||||||
|
|
||||||
var _config = preload("../config/config.gd").new()
|
|
||||||
var _sf_creator = preload("sprite_frames_creator.gd").new()
|
|
||||||
|
|
||||||
func get_importer_name():
|
|
||||||
return "aseprite.wizard.plugin"
|
|
||||||
|
|
||||||
|
|
||||||
func get_visible_name():
|
|
||||||
return "Aseprite Importer"
|
|
||||||
|
|
||||||
|
|
||||||
func get_recognized_extensions():
|
|
||||||
return ["aseprite", "ase"]
|
|
||||||
|
|
||||||
|
|
||||||
func get_save_extension():
|
|
||||||
return "res"
|
|
||||||
|
|
||||||
|
|
||||||
func get_resource_type():
|
|
||||||
return "SpriteFrames"
|
|
||||||
|
|
||||||
|
|
||||||
func get_preset_count():
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
func get_preset_name(i):
|
|
||||||
return "Default"
|
|
||||||
|
|
||||||
|
|
||||||
func get_import_options(i):
|
|
||||||
return [
|
|
||||||
{"name": "split_layers", "default_value": false},
|
|
||||||
{"name": "exclude_layers_pattern", "default_value": ''},
|
|
||||||
{"name": "only_visible_layers", "default_value": false},
|
|
||||||
|
|
||||||
{"name": "sheet_type", "default_value": "Packed", "property_hint": PROPERTY_HINT_ENUM,
|
|
||||||
"hint_string": get_sheet_type_hint_string()},
|
|
||||||
|
|
||||||
{"name": "sprite_filename_pattern", "default_value": "{basename}.{layer}.{extension}"},
|
|
||||||
|
|
||||||
{"name": "texture_strip/import_texture_strip", "default_value": false},
|
|
||||||
{"name": "texture_strip/filename_pattern", "default_value": "{basename}.{layer}.Strip.{extension}"},
|
|
||||||
|
|
||||||
{"name": "texture_atlas/import_texture_atlas", "default_value": false},
|
|
||||||
{"name": "texture_atlas/filename_pattern", "default_value": "{basename}.{layer}.Atlas.{extension}"},
|
|
||||||
{"name": "texture_atlas/frame_filename_pattern", "default_value": "{basename}.{layer}.{animation}.{frame}.Atlas.{extension}"},
|
|
||||||
|
|
||||||
{"name": "animated_texture/import_animated_texture", "default_value": false},
|
|
||||||
{"name": "animated_texture/filename_pattern", "default_value": "{basename}.{layer}.{animation}.Texture.{extension}"},
|
|
||||||
{"name": "animated_texture/frame_filename_pattern", "default_value": "{basename}.{layer}.{animation}.{frame}.Texture.{extension}"},
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
func get_option_visibility(option, options):
|
|
||||||
return true
|
|
||||||
|
|
||||||
|
|
||||||
static func replace_vars(pattern : String, vars : Dictionary):
|
|
||||||
var result = pattern;
|
|
||||||
for k in vars:
|
|
||||||
var v = vars[k]
|
|
||||||
result = result.replace("{%s}" % k, v)
|
|
||||||
return result
|
|
||||||
|
|
||||||
static func get_sheet_type_hint_string() -> String:
|
|
||||||
var hint_string := "Packed"
|
|
||||||
for number in [2, 4, 8, 16, 32]:
|
|
||||||
hint_string += ",%s columns" % number
|
|
||||||
hint_string += ",Strip"
|
|
||||||
return hint_string
|
|
||||||
|
|
||||||
func import(source_file, save_path, options, platform_variants, gen_files):
|
|
||||||
var absolute_source_file = ProjectSettings.globalize_path(source_file)
|
|
||||||
var absolute_save_path = ProjectSettings.globalize_path(save_path)
|
|
||||||
|
|
||||||
var source_path = source_file.substr(0, source_file.find_last('/'))
|
|
||||||
var source_basename = source_file.substr(source_path.length()+1, -1)
|
|
||||||
source_basename = source_basename.substr(0, source_basename.find_last('.'))
|
|
||||||
|
|
||||||
_config.load_config()
|
|
||||||
|
|
||||||
_sf_creator.init(_config)
|
|
||||||
|
|
||||||
var dir = Directory.new()
|
|
||||||
dir.make_dir(save_path)
|
|
||||||
|
|
||||||
# Clear the directories contents
|
|
||||||
dir.open(save_path)
|
|
||||||
dir.list_dir_begin()
|
|
||||||
var file_name = dir.get_next()
|
|
||||||
while file_name != "":
|
|
||||||
if file_name != '.' and file_name != '..':
|
|
||||||
dir.remove(file_name)
|
|
||||||
file_name = dir.get_next()
|
|
||||||
|
|
||||||
var export_mode = _sf_creator.LAYERS_EXPORT_MODE if options['split_layers'] else _sf_creator.FILE_EXPORT_MODE
|
|
||||||
|
|
||||||
var aseprite_opts = {
|
|
||||||
"export_mode": export_mode,
|
|
||||||
"exception_pattern": options['exclude_layers_pattern'],
|
|
||||||
"only_visible_layers": options['only_visible_layers'],
|
|
||||||
"output_filename": '',
|
|
||||||
"column_count" : int(options['sheet_type']) if options['sheet_type'] != "Strip" else 128,
|
|
||||||
}
|
|
||||||
|
|
||||||
var exit_code = _sf_creator.create_resource(absolute_source_file, absolute_save_path, aseprite_opts)
|
|
||||||
if exit_code != OK:
|
|
||||||
printerr("ERROR - Could not import aseprite file: %s" % result_codes.get_error_message(exit_code))
|
|
||||||
return FAILED
|
|
||||||
|
|
||||||
dir.open(save_path)
|
|
||||||
dir.list_dir_begin()
|
|
||||||
|
|
||||||
file_name = dir.get_next()
|
|
||||||
|
|
||||||
var main_sprite_frame_saved = false
|
|
||||||
|
|
||||||
var global_replacement_vars = {
|
|
||||||
"basename": source_basename,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Scan through the import directory and process the generated resources based on what options have been selected.
|
|
||||||
while file_name != "":
|
|
||||||
if file_name != ".." and file_name != ".":
|
|
||||||
if file_name.ends_with(".res"):
|
|
||||||
# This is a SpriteFrames resource generated for a layer.
|
|
||||||
var local_replacement_vars = global_replacement_vars.duplicate()
|
|
||||||
local_replacement_vars["layer"] = file_name.substr(0, file_name.length() - 4)
|
|
||||||
|
|
||||||
if not main_sprite_frame_saved:
|
|
||||||
# Save this resource as the main resource. We need to set something here or Godot won't stop
|
|
||||||
# re-importing the resource. So this is either the SpriteFrames instance of the first layer
|
|
||||||
# (alphabetically) found in the import directory.
|
|
||||||
var sprite_frames : SpriteFrames = ResourceLoader.load("%s/%s" % [save_path, file_name], 'SpriteFrames', true)
|
|
||||||
main_sprite_frame_saved = true
|
|
||||||
var resource_path = "%s.res" % save_path;
|
|
||||||
sprite_frames.take_over_path(resource_path)
|
|
||||||
ResourceSaver.save(resource_path, sprite_frames)
|
|
||||||
|
|
||||||
var sprite_frames : SpriteFrames = ResourceLoader.load("%s/%s" % [save_path, file_name], 'SpriteFrames', true)
|
|
||||||
|
|
||||||
if options["split_layers"]:
|
|
||||||
var sprite_replacement_vars = local_replacement_vars.duplicate()
|
|
||||||
sprite_replacement_vars["extension"] = "res"
|
|
||||||
|
|
||||||
var sprite_filename = "%s/%s" % [source_path, replace_vars(options["sprite_filename_pattern"], sprite_replacement_vars)]
|
|
||||||
ResourceSaver.save(sprite_filename, sprite_frames)
|
|
||||||
sprite_frames.take_over_path(sprite_filename)
|
|
||||||
|
|
||||||
if options["texture_atlas/import_texture_atlas"]:
|
|
||||||
# Create a TextureAtlas resource for this layer.
|
|
||||||
var atlas_texture = null
|
|
||||||
var replacement_vars = local_replacement_vars.duplicate()
|
|
||||||
|
|
||||||
for anim in sprite_frames.animations:
|
|
||||||
var i=0
|
|
||||||
|
|
||||||
replacement_vars["animation"] = anim.name
|
|
||||||
replacement_vars["extension"] = "res"
|
|
||||||
|
|
||||||
for frame in anim.frames:
|
|
||||||
replacement_vars["frame"] = i
|
|
||||||
|
|
||||||
if not atlas_texture:
|
|
||||||
atlas_texture = (frame as AtlasTexture).atlas
|
|
||||||
|
|
||||||
var atlas_filename = "%s/%s" % [source_path, replace_vars(options["texture_atlas/filename_pattern"], replacement_vars)]
|
|
||||||
ResourceSaver.save(atlas_filename, atlas_texture)
|
|
||||||
atlas_texture.take_over_path(atlas_filename)
|
|
||||||
|
|
||||||
frame.atlas = atlas_texture
|
|
||||||
|
|
||||||
var frame_filename = "%s/%s" % [source_path, replace_vars(options["texture_atlas/frame_filename_pattern"], replacement_vars)]
|
|
||||||
ResourceSaver.save(frame_filename, frame)
|
|
||||||
i+=1
|
|
||||||
|
|
||||||
if options["animated_texture/import_animated_texture"]:
|
|
||||||
var replacement_vars = local_replacement_vars.duplicate()
|
|
||||||
replacement_vars["extension"] = "res"
|
|
||||||
|
|
||||||
for anim in sprite_frames.animations:
|
|
||||||
replacement_vars["animation"] = anim.name
|
|
||||||
|
|
||||||
var tex : AnimatedTexture = AnimatedTexture.new()
|
|
||||||
tex.frames = anim.frames.size()
|
|
||||||
|
|
||||||
var i=0
|
|
||||||
for frame in anim.frames:
|
|
||||||
replacement_vars["frame"] = i
|
|
||||||
|
|
||||||
var atlas_tex = frame as AtlasTexture
|
|
||||||
var image : Image = atlas_tex.atlas.get_data()
|
|
||||||
var single_image = Image.new()
|
|
||||||
single_image.create(atlas_tex.get_width(), atlas_tex.get_height(), false, image.get_format())
|
|
||||||
single_image.blit_rect(image, atlas_tex.region, Vector2.ZERO)
|
|
||||||
|
|
||||||
var frame_filename = "%s/%s" % [source_path, replace_vars(options["animated_texture/frame_filename_pattern"], replacement_vars)]
|
|
||||||
|
|
||||||
var res = ImageTexture.new()
|
|
||||||
res.create_from_image(single_image, 0)
|
|
||||||
res.flags = atlas_tex.flags
|
|
||||||
ResourceSaver.save(frame_filename, res)
|
|
||||||
res.take_over_path(frame_filename)
|
|
||||||
|
|
||||||
tex.set_frame_texture(i, res)
|
|
||||||
|
|
||||||
i+=1
|
|
||||||
|
|
||||||
var texture_filename = "%s/%s" % [source_path, replace_vars(options["animated_texture/filename_pattern"], replacement_vars)]
|
|
||||||
ResourceSaver.save(texture_filename, tex)
|
|
||||||
|
|
||||||
elif options['texture_strip/import_texture_strip'] and file_name.ends_with(".png"):
|
|
||||||
var replacement_vars = global_replacement_vars.duplicate()
|
|
||||||
replacement_vars["layer"] = file_name.substr(0, file_name.length() - 4)
|
|
||||||
replacement_vars["extension"] = "png"
|
|
||||||
|
|
||||||
var texture_filename = "%s/%s" % [source_path, replace_vars(options["texture_strip/filename_pattern"], replacement_vars)]
|
|
||||||
|
|
||||||
var img : Image = Image.new()
|
|
||||||
img.load("%s/%s" % [save_path, file_name])
|
|
||||||
var res = ImageTexture.new()
|
|
||||||
res.create_from_image(img, 0)
|
|
||||||
ResourceSaver.save(texture_filename, res)
|
|
||||||
|
|
||||||
file_name = dir.get_next()
|
|
||||||
return OK
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
tool
|
|
||||||
extends EditorInspectorPlugin
|
|
||||||
|
|
||||||
const InspectorDock = preload("animated_sprite_inspector_dock.tscn")
|
|
||||||
|
|
||||||
var config
|
|
||||||
var file_system: EditorFileSystem
|
|
||||||
|
|
||||||
var _sprite: AnimatedSprite
|
|
||||||
|
|
||||||
func can_handle(object):
|
|
||||||
return object is AnimatedSprite
|
|
||||||
|
|
||||||
|
|
||||||
func parse_begin(object):
|
|
||||||
_sprite = object
|
|
||||||
|
|
||||||
|
|
||||||
func parse_end():
|
|
||||||
var dock = InspectorDock.instance()
|
|
||||||
dock.sprite = _sprite
|
|
||||||
dock.config = config
|
|
||||||
dock.file_system = file_system
|
|
||||||
|
|
||||||
add_custom_control(dock)
|
|
||||||
@ -1,178 +0,0 @@
|
|||||||
tool
|
|
||||||
extends PanelContainer
|
|
||||||
|
|
||||||
signal importer_state_changed
|
|
||||||
signal close_requested
|
|
||||||
|
|
||||||
var result_code = preload("../config/result_codes.gd")
|
|
||||||
var _sf_creator = preload("./sprite_frames_creator.gd").new()
|
|
||||||
|
|
||||||
var _config
|
|
||||||
var _file_system: EditorFileSystem
|
|
||||||
|
|
||||||
var _file_dialog_aseprite: FileDialog
|
|
||||||
var _output_folder_dialog: FileDialog
|
|
||||||
var _warning_dialog: AcceptDialog
|
|
||||||
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
_file_dialog_aseprite = _create_aseprite_file_selection()
|
|
||||||
_output_folder_dialog = _create_outuput_folder_selection()
|
|
||||||
_warning_dialog = AcceptDialog.new()
|
|
||||||
|
|
||||||
_sf_creator.init(_config, _file_system)
|
|
||||||
|
|
||||||
get_parent().add_child(_file_dialog_aseprite)
|
|
||||||
get_parent().add_child(_output_folder_dialog)
|
|
||||||
get_parent().add_child(_warning_dialog)
|
|
||||||
|
|
||||||
_load_persisted_config()
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
func _load_persisted_config():
|
|
||||||
_split_mode_field().pressed = _config.should_split_layers()
|
|
||||||
_only_visible_layers_field().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().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 _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 = FileDialog.new()
|
|
||||||
file_dialog.mode = FileDialog.MODE_OPEN_FILE
|
|
||||||
file_dialog.access = FileDialog.ACCESS_FILESYSTEM
|
|
||||||
file_dialog.connect("file_selected", self, "_on_aseprite_file_selected")
|
|
||||||
file_dialog.set_filters(PoolStringArray(["*.ase","*.aseprite"]))
|
|
||||||
return file_dialog
|
|
||||||
|
|
||||||
|
|
||||||
func _create_outuput_folder_selection():
|
|
||||||
var file_dialog = FileDialog.new()
|
|
||||||
file_dialog.mode = FileDialog.MODE_OPEN_DIR
|
|
||||||
file_dialog.access = FileDialog.ACCESS_RESOURCES
|
|
||||||
file_dialog.connect("dir_selected", self, "_on_output_folder_selected")
|
|
||||||
return file_dialog
|
|
||||||
|
|
||||||
|
|
||||||
func _on_aseprite_file_selected(path):
|
|
||||||
_file_location_field().text = path
|
|
||||||
_config.set_last_source_path(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().pressed
|
|
||||||
|
|
||||||
var export_mode = _sf_creator.LAYERS_EXPORT_MODE if split_layers else _sf_creator.FILE_EXPORT_MODE
|
|
||||||
var options = {
|
|
||||||
"export_mode": export_mode,
|
|
||||||
"exception_pattern": _exception_pattern_field().text,
|
|
||||||
"only_visible_layers": _only_visible_layers_field().pressed,
|
|
||||||
"output_filename": _custom_name_field().text,
|
|
||||||
"do_not_create_resource": _do_not_create_res_field().pressed,
|
|
||||||
"remove_source_files_allowed": true
|
|
||||||
}
|
|
||||||
var exit_code = _sf_creator.create_resource(aseprite_file, output_location, options)
|
|
||||||
if exit_code is GDScriptFunctionState:
|
|
||||||
exit_code = yield(exit_code, "completed")
|
|
||||||
|
|
||||||
if exit_code != 0:
|
|
||||||
_show_error(exit_code)
|
|
||||||
return
|
|
||||||
_show_import_success_message()
|
|
||||||
|
|
||||||
|
|
||||||
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().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().pressed)
|
|
||||||
_config.set_do_not_create_resource(_do_not_create_res_field().pressed)
|
|
||||||
_config.save()
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
@ -1,310 +0,0 @@
|
|||||||
tool
|
|
||||||
extends Reference
|
|
||||||
|
|
||||||
var result_code = preload("../config/result_codes.gd")
|
|
||||||
var _aseprite = preload("../aseprite/aseprite.gd").new()
|
|
||||||
|
|
||||||
enum {
|
|
||||||
FILE_EXPORT_MODE,
|
|
||||||
LAYERS_EXPORT_MODE
|
|
||||||
}
|
|
||||||
|
|
||||||
var _config
|
|
||||||
var _file_system: EditorFileSystem
|
|
||||||
var _should_check_file_system := false
|
|
||||||
|
|
||||||
|
|
||||||
func init(config, editor_file_system: EditorFileSystem = null):
|
|
||||||
_config = config
|
|
||||||
_file_system = editor_file_system
|
|
||||||
_should_check_file_system = _file_system != null
|
|
||||||
_aseprite.init(config)
|
|
||||||
|
|
||||||
|
|
||||||
func _loop_config_prefix() -> String:
|
|
||||||
return _config.get_animation_loop_exception_prefix()
|
|
||||||
|
|
||||||
|
|
||||||
func _is_loop_config_enabled() -> String:
|
|
||||||
return _config.is_default_animation_loop_enabled()
|
|
||||||
|
|
||||||
|
|
||||||
func create_animations(sprite: AnimatedSprite, options: Dictionary):
|
|
||||||
if not _aseprite.test_command():
|
|
||||||
return result_code.ERR_ASEPRITE_CMD_NOT_FOUND
|
|
||||||
|
|
||||||
var dir = Directory.new()
|
|
||||||
if not dir.file_exists(options.source):
|
|
||||||
return result_code.ERR_SOURCE_FILE_NOT_FOUND
|
|
||||||
|
|
||||||
if not dir.dir_exists(options.output_folder):
|
|
||||||
return result_code.ERR_OUTPUT_FOLDER_NOT_FOUND
|
|
||||||
|
|
||||||
var result = _create_animations_from_file(sprite, options)
|
|
||||||
|
|
||||||
if result is GDScriptFunctionState:
|
|
||||||
result = yield(result, "completed")
|
|
||||||
|
|
||||||
if result != result_code.SUCCESS:
|
|
||||||
printerr(result_code.get_error_message(result))
|
|
||||||
|
|
||||||
|
|
||||||
func _create_animations_from_file(sprite: AnimatedSprite, options: Dictionary):
|
|
||||||
var output
|
|
||||||
|
|
||||||
if options.get("layer", "") == "":
|
|
||||||
output = _aseprite.export_file(options.source, options.output_folder, options)
|
|
||||||
else:
|
|
||||||
output = _aseprite.export_layer(options.source, options.layer, options.output_folder, options)
|
|
||||||
|
|
||||||
if output.empty():
|
|
||||||
return result_code.ERR_ASEPRITE_EXPORT_FAILED
|
|
||||||
yield(_scan_filesystem(), "completed")
|
|
||||||
|
|
||||||
var result = _import(output, sprite)
|
|
||||||
|
|
||||||
if _config.should_remove_source_files():
|
|
||||||
var dir = Directory.new()
|
|
||||||
dir.remove(output.data_file)
|
|
||||||
yield(_scan_filesystem(), "completed")
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
func create_resource(source_file: String, output_folder: String, options = {}):
|
|
||||||
var export_mode = options.get('export_mode', FILE_EXPORT_MODE)
|
|
||||||
|
|
||||||
if not _aseprite.test_command():
|
|
||||||
return result_code.ERR_ASEPRITE_CMD_NOT_FOUND
|
|
||||||
|
|
||||||
var dir = Directory.new()
|
|
||||||
if not dir.file_exists(source_file):
|
|
||||||
return result_code.ERR_SOURCE_FILE_NOT_FOUND
|
|
||||||
|
|
||||||
if not dir.dir_exists(output_folder):
|
|
||||||
return result_code.ERR_OUTPUT_FOLDER_NOT_FOUND
|
|
||||||
|
|
||||||
match export_mode:
|
|
||||||
FILE_EXPORT_MODE:
|
|
||||||
if _should_check_file_system:
|
|
||||||
return yield(create_sprite_frames_from_aseprite_file(source_file, output_folder, options), "completed")
|
|
||||||
return create_sprite_frames_from_aseprite_file(source_file, output_folder, options)
|
|
||||||
LAYERS_EXPORT_MODE:
|
|
||||||
if _should_check_file_system:
|
|
||||||
return yield(create_sprite_frames_from_aseprite_layers(source_file, output_folder, options), "completed")
|
|
||||||
return create_sprite_frames_from_aseprite_layers(source_file, output_folder, options)
|
|
||||||
_:
|
|
||||||
return result_code.ERR_UNKNOWN_EXPORT_MODE
|
|
||||||
|
|
||||||
|
|
||||||
func create_sprite_frames_from_aseprite_file(source_file: String, output_folder: String, options: Dictionary):
|
|
||||||
var output = _aseprite.export_file(source_file, output_folder, options)
|
|
||||||
if output.empty():
|
|
||||||
return result_code.ERR_ASEPRITE_EXPORT_FAILED
|
|
||||||
|
|
||||||
if (_should_check_file_system):
|
|
||||||
yield(_scan_filesystem(), "completed")
|
|
||||||
|
|
||||||
if options.get("do_not_create_resource", false):
|
|
||||||
return OK
|
|
||||||
|
|
||||||
var result = _import(output)
|
|
||||||
|
|
||||||
if options.get("remove_source_files_allowed", false) and _config.should_remove_source_files():
|
|
||||||
var dir = Directory.new()
|
|
||||||
dir.remove(output.data_file)
|
|
||||||
if (_should_check_file_system):
|
|
||||||
yield(_scan_filesystem(), "completed")
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
func create_sprite_frames_from_aseprite_layers(source_file: String, output_folder: String, options: Dictionary):
|
|
||||||
var output = _aseprite.export_layers(source_file, output_folder, options)
|
|
||||||
if output.empty():
|
|
||||||
return result_code.ERR_NO_VALID_LAYERS_FOUND
|
|
||||||
|
|
||||||
var result = OK
|
|
||||||
|
|
||||||
if (_should_check_file_system):
|
|
||||||
yield(_scan_filesystem(), "completed")
|
|
||||||
|
|
||||||
var should_remove_source = options.get("remove_source_files_allowed", false) and _config.should_remove_source_files()
|
|
||||||
|
|
||||||
for o in output:
|
|
||||||
if o.empty():
|
|
||||||
result = result_code.ERR_ASEPRITE_EXPORT_FAILED
|
|
||||||
else:
|
|
||||||
if options.get("do_not_create_resource", false):
|
|
||||||
result = OK
|
|
||||||
else:
|
|
||||||
result = _import(o)
|
|
||||||
if should_remove_source:
|
|
||||||
var dir = Directory.new()
|
|
||||||
dir.remove(o.data_file)
|
|
||||||
|
|
||||||
if should_remove_source and _should_check_file_system:
|
|
||||||
yield(_scan_filesystem(), "completed")
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
func _get_file_basename(file_path: String) -> String:
|
|
||||||
return file_path.get_file().trim_suffix('.%s' % file_path.get_extension())
|
|
||||||
|
|
||||||
|
|
||||||
func _import(data, animated_sprite = null) -> int:
|
|
||||||
var source_file = data.data_file
|
|
||||||
var sprite_sheet = data.sprite_sheet
|
|
||||||
var file = File.new()
|
|
||||||
var err = file.open(source_file, File.READ)
|
|
||||||
if err != OK:
|
|
||||||
return err
|
|
||||||
var content = parse_json(file.get_as_text())
|
|
||||||
|
|
||||||
if not _aseprite.is_valid_spritesheet(content):
|
|
||||||
return result_code.ERR_INVALID_ASEPRITE_SPRITESHEET
|
|
||||||
|
|
||||||
var texture = _parse_texture_path(sprite_sheet)
|
|
||||||
|
|
||||||
var resource = _create_sprite_frames_with_animations(content, texture)
|
|
||||||
|
|
||||||
if is_instance_valid(animated_sprite):
|
|
||||||
animated_sprite.frames = resource
|
|
||||||
return result_code.SUCCESS
|
|
||||||
|
|
||||||
var save_path = "%s.%s" % [source_file.get_basename(), "res"]
|
|
||||||
var code = ResourceSaver.save(save_path, resource, ResourceSaver.FLAG_REPLACE_SUBRESOURCE_PATHS)
|
|
||||||
resource.take_over_path(save_path)
|
|
||||||
return code
|
|
||||||
|
|
||||||
|
|
||||||
func _create_sprite_frames_with_animations(content, texture) -> SpriteFrames:
|
|
||||||
var frame_cache = {}
|
|
||||||
var frames = _aseprite.get_content_frames(content)
|
|
||||||
var sprite_frames := SpriteFrames.new()
|
|
||||||
sprite_frames.remove_animation("default")
|
|
||||||
|
|
||||||
if content.meta.has("frameTags") and content.meta.frameTags.size() > 0:
|
|
||||||
for tag in content.meta.frameTags:
|
|
||||||
var selected_frames = frames.slice(tag.from, tag.to)
|
|
||||||
_add_animation_frames(sprite_frames, tag.name, selected_frames, texture, tag.direction, frame_cache)
|
|
||||||
else:
|
|
||||||
_add_animation_frames(sprite_frames, "default", frames, texture)
|
|
||||||
|
|
||||||
return sprite_frames
|
|
||||||
|
|
||||||
|
|
||||||
func _add_animation_frames(
|
|
||||||
sprite_frames: SpriteFrames,
|
|
||||||
anim_name: String,
|
|
||||||
frames : Array,
|
|
||||||
texture,
|
|
||||||
direction = 'forward',
|
|
||||||
frame_cache = {}
|
|
||||||
):
|
|
||||||
|
|
||||||
var animation_name := anim_name
|
|
||||||
var is_loopable = _is_loop_config_enabled()
|
|
||||||
|
|
||||||
var loop_prefix := _loop_config_prefix()
|
|
||||||
if animation_name.begins_with(loop_prefix):
|
|
||||||
animation_name = anim_name.trim_prefix(loop_prefix)
|
|
||||||
is_loopable = not is_loopable
|
|
||||||
|
|
||||||
sprite_frames.add_animation(animation_name)
|
|
||||||
|
|
||||||
var min_duration = _get_min_duration(frames)
|
|
||||||
var fps = _calculate_fps(min_duration)
|
|
||||||
|
|
||||||
if direction == 'reverse':
|
|
||||||
frames.invert()
|
|
||||||
|
|
||||||
for frame in frames:
|
|
||||||
_add_to_sprite_frames(sprite_frames, animation_name, texture, frame, min_duration, frame_cache)
|
|
||||||
|
|
||||||
if direction == 'pingpong':
|
|
||||||
frames.remove(frames.size() - 1)
|
|
||||||
if is_loopable:
|
|
||||||
frames.remove(0)
|
|
||||||
frames.invert()
|
|
||||||
|
|
||||||
for frame in frames:
|
|
||||||
_add_to_sprite_frames(sprite_frames, animation_name, texture, frame, min_duration, frame_cache)
|
|
||||||
|
|
||||||
sprite_frames.set_animation_loop(animation_name, is_loopable)
|
|
||||||
sprite_frames.set_animation_speed(animation_name, fps)
|
|
||||||
|
|
||||||
|
|
||||||
func _calculate_fps(min_duration: int) -> float:
|
|
||||||
return ceil(1000.0 / min_duration)
|
|
||||||
|
|
||||||
|
|
||||||
func _get_min_duration(frames) -> int:
|
|
||||||
var min_duration = 100000
|
|
||||||
for frame in frames:
|
|
||||||
if frame.duration < min_duration:
|
|
||||||
min_duration = frame.duration
|
|
||||||
return min_duration
|
|
||||||
|
|
||||||
|
|
||||||
func _parse_texture_path(path):
|
|
||||||
if not _should_check_file_system and not ResourceLoader.has_cached(path):
|
|
||||||
# this is a fallback for the importer. It generates the spritesheet file when it hasn't
|
|
||||||
# been imported before. Files generated in this method are usually
|
|
||||||
# bigger in size than the ones imported by Godot's default importer.
|
|
||||||
var image = Image.new()
|
|
||||||
image.load(path)
|
|
||||||
var texture = ImageTexture.new()
|
|
||||||
texture.create_from_image(image, 0)
|
|
||||||
return texture
|
|
||||||
|
|
||||||
return ResourceLoader.load(path, 'Image', true)
|
|
||||||
|
|
||||||
|
|
||||||
func _add_to_sprite_frames(
|
|
||||||
sprite_frames,
|
|
||||||
animation_name: String,
|
|
||||||
texture,
|
|
||||||
frame: Dictionary,
|
|
||||||
min_duration: int,
|
|
||||||
frame_cache: Dictionary
|
|
||||||
):
|
|
||||||
var atlas : AtlasTexture = _create_atlastexture_from_frame(texture, frame, sprite_frames, frame_cache)
|
|
||||||
|
|
||||||
var number_of_sprites = ceil(frame.duration / min_duration)
|
|
||||||
for _i in range(number_of_sprites):
|
|
||||||
sprite_frames.add_frame(animation_name, atlas)
|
|
||||||
|
|
||||||
|
|
||||||
func _create_atlastexture_from_frame(
|
|
||||||
image,
|
|
||||||
frame_data,
|
|
||||||
sprite_frames: SpriteFrames,
|
|
||||||
frame_cache: Dictionary
|
|
||||||
) -> AtlasTexture:
|
|
||||||
var frame = frame_data.frame
|
|
||||||
var region := Rect2(frame.x, frame.y, frame.w, frame.h)
|
|
||||||
var key := "%s_%s_%s_%s" % [frame.x, frame.y, frame.w, frame.h]
|
|
||||||
|
|
||||||
var texture = frame_cache.get(key)
|
|
||||||
|
|
||||||
if texture != null and texture.atlas == image:
|
|
||||||
return texture
|
|
||||||
|
|
||||||
var atlas_texture := AtlasTexture.new()
|
|
||||||
atlas_texture.atlas = image
|
|
||||||
atlas_texture.region = region
|
|
||||||
|
|
||||||
frame_cache[key] = atlas_texture
|
|
||||||
|
|
||||||
return atlas_texture
|
|
||||||
|
|
||||||
|
|
||||||
func _scan_filesystem():
|
|
||||||
_file_system.scan()
|
|
||||||
yield(_file_system, "filesystem_changed")
|
|
||||||
|
|
||||||
|
|
||||||
func list_layers(file: String, only_visibles = false) -> Array:
|
|
||||||
return _aseprite.list_layers(file, only_visibles)
|
|
||||||
@ -1,204 +0,0 @@
|
|||||||
extends Reference
|
|
||||||
|
|
||||||
var result_code = preload("../config/result_codes.gd")
|
|
||||||
var _aseprite = preload("../aseprite/aseprite.gd").new()
|
|
||||||
|
|
||||||
var _config
|
|
||||||
var _file_system
|
|
||||||
|
|
||||||
func init(config, editor_file_system: EditorFileSystem = null):
|
|
||||||
_config = config
|
|
||||||
_file_system = editor_file_system
|
|
||||||
_aseprite.init(config)
|
|
||||||
|
|
||||||
|
|
||||||
func create_animations(sprite: Sprite, player: AnimationPlayer, options: Dictionary):
|
|
||||||
if not _aseprite.test_command():
|
|
||||||
return result_code.ERR_ASEPRITE_CMD_NOT_FOUND
|
|
||||||
|
|
||||||
var dir = Directory.new()
|
|
||||||
if not dir.file_exists(options.source):
|
|
||||||
return result_code.ERR_SOURCE_FILE_NOT_FOUND
|
|
||||||
|
|
||||||
if not dir.dir_exists(options.output_folder):
|
|
||||||
return result_code.ERR_OUTPUT_FOLDER_NOT_FOUND
|
|
||||||
|
|
||||||
var result = _create_animations_from_file(sprite, player, options)
|
|
||||||
if result is GDScriptFunctionState:
|
|
||||||
result = yield(result, "completed")
|
|
||||||
|
|
||||||
if result != result_code.SUCCESS:
|
|
||||||
printerr(result_code.get_error_message(result))
|
|
||||||
|
|
||||||
|
|
||||||
func _create_animations_from_file(sprite: Sprite, player: AnimationPlayer, options: Dictionary):
|
|
||||||
var output
|
|
||||||
|
|
||||||
if options.get("layer", "") == "":
|
|
||||||
output = _aseprite.export_file(options.source, options.output_folder, options)
|
|
||||||
else:
|
|
||||||
output = _aseprite.export_layer(options.source, options.layer, options.output_folder, options)
|
|
||||||
|
|
||||||
if output.empty():
|
|
||||||
return result_code.ERR_ASEPRITE_EXPORT_FAILED
|
|
||||||
yield(_scan_filesystem(), "completed")
|
|
||||||
|
|
||||||
var result = _import(sprite, player, output)
|
|
||||||
|
|
||||||
if _config.should_remove_source_files():
|
|
||||||
var dir = Directory.new()
|
|
||||||
dir.remove(output.data_file)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
func _import(sprite: Sprite, player: AnimationPlayer, data: Dictionary):
|
|
||||||
var source_file = data.data_file
|
|
||||||
var sprite_sheet = data.sprite_sheet
|
|
||||||
|
|
||||||
var file = File.new()
|
|
||||||
var err = file.open(source_file, File.READ)
|
|
||||||
if err != OK:
|
|
||||||
return err
|
|
||||||
|
|
||||||
var content = parse_json(file.get_as_text())
|
|
||||||
|
|
||||||
if not _aseprite.is_valid_spritesheet(content):
|
|
||||||
return result_code.ERR_INVALID_ASEPRITE_SPRITESHEET
|
|
||||||
|
|
||||||
_load_texture(sprite, sprite_sheet, content)
|
|
||||||
var result = _configure_animations(sprite, player, content)
|
|
||||||
if result != result_code.SUCCESS:
|
|
||||||
return result
|
|
||||||
|
|
||||||
return _cleanup_animations(sprite, player, content)
|
|
||||||
|
|
||||||
|
|
||||||
func _load_texture(sprite: Sprite, sprite_sheet: String, content: Dictionary):
|
|
||||||
var texture = ResourceLoader.load(sprite_sheet, 'Image', true)
|
|
||||||
sprite.texture = texture
|
|
||||||
|
|
||||||
if content.frames.empty():
|
|
||||||
return
|
|
||||||
|
|
||||||
sprite.hframes = content.meta.size.w / content.frames[0].sourceSize.w
|
|
||||||
sprite.vframes = content.meta.size.h / content.frames[0].sourceSize.h
|
|
||||||
|
|
||||||
|
|
||||||
func _configure_animations(sprite: Sprite, player: AnimationPlayer, content: Dictionary):
|
|
||||||
var frames = _aseprite.get_content_frames(content)
|
|
||||||
if content.meta.has("frameTags") and content.meta.frameTags.size() > 0:
|
|
||||||
var result = result_code.SUCCESS
|
|
||||||
for tag in content.meta.frameTags:
|
|
||||||
var selected_frames = frames.slice(tag.from, tag.to)
|
|
||||||
result = _add_animation_frames(sprite, player, tag.name, selected_frames, tag.direction)
|
|
||||||
if result != result_code.SUCCESS:
|
|
||||||
break
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
return _add_animation_frames(sprite, player, "default", frames)
|
|
||||||
|
|
||||||
|
|
||||||
func _add_animation_frames(sprite: Sprite, player: AnimationPlayer, anim_name: String, frames: Array, direction = 'forward'):
|
|
||||||
var animation_name = anim_name
|
|
||||||
var is_loopable = _config.is_default_animation_loop_enabled()
|
|
||||||
|
|
||||||
if animation_name.begins_with(_config.get_animation_loop_exception_prefix()):
|
|
||||||
animation_name = anim_name.substr(_config.get_animation_loop_exception_prefix().length())
|
|
||||||
is_loopable = not is_loopable
|
|
||||||
|
|
||||||
if not player.has_animation(animation_name):
|
|
||||||
player.add_animation(animation_name, Animation.new())
|
|
||||||
|
|
||||||
var animation = player.get_animation(animation_name)
|
|
||||||
var track = _get_frame_track_path(player, sprite)
|
|
||||||
var track_index = _create_frame_track(sprite, animation, track)
|
|
||||||
|
|
||||||
if direction == 'reverse':
|
|
||||||
frames.invert()
|
|
||||||
|
|
||||||
var animation_length = 0
|
|
||||||
|
|
||||||
for frame in frames:
|
|
||||||
var frame_index = _calculate_frame_index(sprite, frame)
|
|
||||||
animation.track_insert_key(track_index, animation_length, frame_index)
|
|
||||||
animation_length += frame.duration / 1000
|
|
||||||
|
|
||||||
if direction == 'pingpong':
|
|
||||||
frames.remove(frames.size() - 1)
|
|
||||||
if is_loopable:
|
|
||||||
frames.remove(0)
|
|
||||||
frames.invert()
|
|
||||||
|
|
||||||
for frame in frames:
|
|
||||||
var frame_index = _calculate_frame_index(sprite, frame)
|
|
||||||
animation.track_insert_key(track_index, animation_length, frame_index)
|
|
||||||
animation_length += frame.duration / 1000
|
|
||||||
|
|
||||||
animation.length = animation_length
|
|
||||||
animation.loop = is_loopable
|
|
||||||
|
|
||||||
return result_code.SUCCESS
|
|
||||||
|
|
||||||
|
|
||||||
func _calculate_frame_index(sprite: Sprite, frame: Dictionary) -> int:
|
|
||||||
var column = floor(frame.frame.x * sprite.hframes / sprite.texture.get_width())
|
|
||||||
var row = floor(frame.frame.y * sprite.vframes / sprite.texture.get_height())
|
|
||||||
return (row * sprite.hframes) + column
|
|
||||||
|
|
||||||
|
|
||||||
func _create_frame_track(sprite: Sprite, animation: Animation, track: String):
|
|
||||||
var track_index = animation.find_track(track)
|
|
||||||
|
|
||||||
if track_index != -1:
|
|
||||||
animation.remove_track(track_index)
|
|
||||||
|
|
||||||
track_index = animation.add_track(Animation.TYPE_VALUE)
|
|
||||||
animation.track_set_path(track_index, track)
|
|
||||||
animation.track_set_interpolation_loop_wrap(track_index, false)
|
|
||||||
animation.value_track_set_update_mode(track_index, Animation.UPDATE_DISCRETE)
|
|
||||||
|
|
||||||
return track_index
|
|
||||||
|
|
||||||
|
|
||||||
func _get_frame_track_path(player: AnimationPlayer, sprite: Sprite):
|
|
||||||
var node_path = player.get_node(player.root_node).get_path_to(sprite)
|
|
||||||
return "%s:frame" % node_path
|
|
||||||
|
|
||||||
|
|
||||||
func _cleanup_animations(sprite: Sprite, player: AnimationPlayer, content: Dictionary):
|
|
||||||
if not (content.meta.has("frameTags") and content.meta.frameTags.size() > 0):
|
|
||||||
return result_code.SUCCESS
|
|
||||||
|
|
||||||
var track = _get_frame_track_path(player, sprite)
|
|
||||||
var tags = ["RESET"]
|
|
||||||
for t in content.meta.frameTags:
|
|
||||||
var a = t.name
|
|
||||||
if a.begins_with(_config.get_animation_loop_exception_prefix()):
|
|
||||||
a = a.substr(_config.get_animation_loop_exception_prefix().length())
|
|
||||||
tags.push_back(a)
|
|
||||||
|
|
||||||
for a in player.get_animation_list():
|
|
||||||
if tags.has(a):
|
|
||||||
continue
|
|
||||||
|
|
||||||
var animation = player.get_animation(a)
|
|
||||||
|
|
||||||
if animation.get_track_count() != 1:
|
|
||||||
var t = animation.find_track(track)
|
|
||||||
if t != -1:
|
|
||||||
animation.remove_track(t)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if animation.find_track(track) != -1:
|
|
||||||
player.remove_animation(a)
|
|
||||||
|
|
||||||
return result_code.SUCCESS
|
|
||||||
|
|
||||||
func _scan_filesystem():
|
|
||||||
_file_system.scan()
|
|
||||||
yield(_file_system, "filesystem_changed")
|
|
||||||
|
|
||||||
|
|
||||||
func list_layers(file: String, only_visibles = false) -> Array:
|
|
||||||
return _aseprite.list_layers(file, only_visibles)
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
tool
|
|
||||||
extends EditorInspectorPlugin
|
|
||||||
|
|
||||||
const InspectorDock = preload("sprite_inspector_dock.tscn")
|
|
||||||
|
|
||||||
var config
|
|
||||||
var file_system: EditorFileSystem
|
|
||||||
|
|
||||||
var _sprite: Sprite
|
|
||||||
|
|
||||||
func can_handle(object):
|
|
||||||
return object is Sprite
|
|
||||||
|
|
||||||
|
|
||||||
func parse_begin(object):
|
|
||||||
_sprite = object
|
|
||||||
|
|
||||||
|
|
||||||
func parse_end():
|
|
||||||
var dock = InspectorDock.instance()
|
|
||||||
dock.sprite = _sprite
|
|
||||||
dock.config = config
|
|
||||||
dock.file_system = file_system
|
|
||||||
|
|
||||||
add_custom_control(dock)
|
|
||||||
@ -1,256 +0,0 @@
|
|||||||
tool
|
|
||||||
extends PanelContainer
|
|
||||||
|
|
||||||
const wizard_config = preload("../config/wizard_config.gd")
|
|
||||||
const result_code = preload("../config/result_codes.gd")
|
|
||||||
var animation_creator = preload("animation_creator.gd").new()
|
|
||||||
|
|
||||||
var scene: Node
|
|
||||||
var sprite: Sprite
|
|
||||||
|
|
||||||
var config
|
|
||||||
var file_system: EditorFileSystem
|
|
||||||
|
|
||||||
var _layer: String = ""
|
|
||||||
var _source: String = ""
|
|
||||||
var _animation_player_path: String
|
|
||||||
var _file_dialog_aseprite: FileDialog
|
|
||||||
var _output_folder_dialog: FileDialog
|
|
||||||
var _importing := false
|
|
||||||
|
|
||||||
var _output_folder := ""
|
|
||||||
var _out_folder_default := "[Same as scene]"
|
|
||||||
var _layer_default := "[all]"
|
|
||||||
|
|
||||||
onready var _options_field = $margin/VBoxContainer/animation_player/options
|
|
||||||
onready var _source_field = $margin/VBoxContainer/source/button
|
|
||||||
onready var _layer_field = $margin/VBoxContainer/layer/options
|
|
||||||
onready var _options_title = $margin/VBoxContainer/options_title/options_title
|
|
||||||
onready var _options_container = $margin/VBoxContainer/options
|
|
||||||
onready var _out_folder_field = $margin/VBoxContainer/options/out_folder/button
|
|
||||||
onready var _out_filename_field = $margin/VBoxContainer/options/out_filename/LineEdit
|
|
||||||
onready var _visible_layers_field = $margin/VBoxContainer/options/visible_layers/CheckButton
|
|
||||||
onready var _ex_pattern_field = $margin/VBoxContainer/options/ex_pattern/LineEdit
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
var cfg = wizard_config.decode(sprite.editor_description)
|
|
||||||
|
|
||||||
if cfg == null:
|
|
||||||
_load_default_config()
|
|
||||||
else:
|
|
||||||
_load_config(cfg)
|
|
||||||
|
|
||||||
animation_creator.init(config, file_system)
|
|
||||||
|
|
||||||
|
|
||||||
func _load_config(cfg):
|
|
||||||
if cfg.has("source"):
|
|
||||||
_set_source(cfg.source)
|
|
||||||
|
|
||||||
if cfg.has("player"):
|
|
||||||
_set_animation_player(cfg.player)
|
|
||||||
|
|
||||||
if cfg.get("layer", "") != "":
|
|
||||||
_set_layer(cfg.layer)
|
|
||||||
|
|
||||||
_output_folder = cfg.get("o_folder", "")
|
|
||||||
_out_folder_field.text = _output_folder if _output_folder != "" else _out_folder_default
|
|
||||||
_out_filename_field.text = cfg.get("o_name", "")
|
|
||||||
_visible_layers_field.pressed = cfg.get("only_visible", "") == "True"
|
|
||||||
_ex_pattern_field.text = cfg.get("o_ex_p", "")
|
|
||||||
|
|
||||||
_set_options_visible(cfg.get("op_exp", "false") == "True")
|
|
||||||
|
|
||||||
|
|
||||||
func _load_default_config():
|
|
||||||
_ex_pattern_field.text = config.get_default_exclusion_pattern()
|
|
||||||
_set_options_visible(false)
|
|
||||||
|
|
||||||
|
|
||||||
func _set_source(source):
|
|
||||||
_source = source
|
|
||||||
_source_field.text = _source
|
|
||||||
_source_field.hint_tooltip = _source
|
|
||||||
|
|
||||||
|
|
||||||
func _set_animation_player(player):
|
|
||||||
_animation_player_path = player
|
|
||||||
_options_field.add_item(_animation_player_path)
|
|
||||||
|
|
||||||
|
|
||||||
func _set_layer(layer):
|
|
||||||
_layer = layer
|
|
||||||
_layer_field.add_item(_layer)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_options_pressed():
|
|
||||||
var animation_players = []
|
|
||||||
var root = get_tree().get_edited_scene_root()
|
|
||||||
_find_animation_players(root, root, animation_players)
|
|
||||||
|
|
||||||
var current = 0
|
|
||||||
_options_field.clear()
|
|
||||||
_options_field.add_item("[empty]")
|
|
||||||
|
|
||||||
for ap in animation_players:
|
|
||||||
_options_field.add_item(ap)
|
|
||||||
if ap == _animation_player_path:
|
|
||||||
current = _options_field.get_item_count() - 1
|
|
||||||
|
|
||||||
_options_field.select(current)
|
|
||||||
|
|
||||||
|
|
||||||
func _find_animation_players(root: Node, node: Node, players: Array):
|
|
||||||
if node is AnimationPlayer:
|
|
||||||
players.push_back(root.get_path_to(node))
|
|
||||||
|
|
||||||
for c in node.get_children():
|
|
||||||
_find_animation_players(root, c, players)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_options_item_selected(index):
|
|
||||||
if index == 0:
|
|
||||||
_animation_player_path = ""
|
|
||||||
return
|
|
||||||
_animation_player_path = _options_field.get_item_text(index)
|
|
||||||
_save_config()
|
|
||||||
|
|
||||||
|
|
||||||
func _on_layer_pressed():
|
|
||||||
if _source == "":
|
|
||||||
_show_message("Please. Select source file first.")
|
|
||||||
return
|
|
||||||
|
|
||||||
var layers = animation_creator.list_layers(ProjectSettings.globalize_path(_source))
|
|
||||||
var current = 0
|
|
||||||
_layer_field.clear()
|
|
||||||
_layer_field.add_item("[all]")
|
|
||||||
|
|
||||||
for l in layers:
|
|
||||||
if l == "":
|
|
||||||
continue
|
|
||||||
|
|
||||||
_layer_field.add_item(l)
|
|
||||||
if l == _layer:
|
|
||||||
current = _layer_field.get_item_count() - 1
|
|
||||||
_layer_field.select(current)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_layer_item_selected(index):
|
|
||||||
if index == 0:
|
|
||||||
_layer = ""
|
|
||||||
return
|
|
||||||
_layer = _layer_field.get_item_text(index)
|
|
||||||
_save_config()
|
|
||||||
|
|
||||||
|
|
||||||
func _on_source_pressed():
|
|
||||||
_open_source_dialog()
|
|
||||||
|
|
||||||
|
|
||||||
func _on_import_pressed():
|
|
||||||
if _importing:
|
|
||||||
return
|
|
||||||
_importing = true
|
|
||||||
|
|
||||||
var root = get_tree().get_edited_scene_root()
|
|
||||||
|
|
||||||
if _animation_player_path == "" or not root.has_node(_animation_player_path):
|
|
||||||
_show_message("AnimationPlayer not found")
|
|
||||||
_importing = false
|
|
||||||
return
|
|
||||||
|
|
||||||
if _source == "":
|
|
||||||
_show_message("Aseprite file not selected")
|
|
||||||
_importing = false
|
|
||||||
return
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
"source": ProjectSettings.globalize_path(_source),
|
|
||||||
"output_folder": _output_folder if _output_folder != "" else root.filename.get_base_dir(),
|
|
||||||
"exception_pattern": _ex_pattern_field.text,
|
|
||||||
"only_visible_layers": _visible_layers_field.pressed,
|
|
||||||
"output_filename": _out_filename_field.text,
|
|
||||||
"layer": _layer
|
|
||||||
}
|
|
||||||
|
|
||||||
_save_config()
|
|
||||||
|
|
||||||
animation_creator.create_animations(sprite, root.get_node(_animation_player_path), options)
|
|
||||||
_importing = false
|
|
||||||
|
|
||||||
|
|
||||||
func _save_config():
|
|
||||||
sprite.editor_description = wizard_config.encode({
|
|
||||||
"player": _animation_player_path,
|
|
||||||
"source": _source,
|
|
||||||
"layer": _layer,
|
|
||||||
"op_exp": _options_title.pressed,
|
|
||||||
"o_folder": _output_folder,
|
|
||||||
"o_name": _out_filename_field.text,
|
|
||||||
"only_visible": _visible_layers_field.pressed,
|
|
||||||
"o_ex_p": _ex_pattern_field.text
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
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 = _source.get_base_dir()
|
|
||||||
_file_dialog_aseprite.popup_centered_ratio()
|
|
||||||
|
|
||||||
|
|
||||||
func _create_aseprite_file_selection():
|
|
||||||
var file_dialog = FileDialog.new()
|
|
||||||
file_dialog.mode = FileDialog.MODE_OPEN_FILE
|
|
||||||
file_dialog.access = FileDialog.ACCESS_FILESYSTEM
|
|
||||||
file_dialog.connect("file_selected", self, "_on_aseprite_file_selected")
|
|
||||||
file_dialog.set_filters(PoolStringArray(["*.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 _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", _warning_dialog, "queue_free")
|
|
||||||
|
|
||||||
|
|
||||||
func _on_options_title_toggled(button_pressed):
|
|
||||||
_set_options_visible(button_pressed)
|
|
||||||
_save_config()
|
|
||||||
|
|
||||||
|
|
||||||
func _set_options_visible(is_visible):
|
|
||||||
_options_container.visible = is_visible
|
|
||||||
_options_title.icon = config.get_icon_arrow_down() if is_visible else config.get_icon_arrow_right()
|
|
||||||
|
|
||||||
|
|
||||||
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 = FileDialog.new()
|
|
||||||
file_dialog.mode = FileDialog.MODE_OPEN_DIR
|
|
||||||
file_dialog.access = FileDialog.ACCESS_RESOURCES
|
|
||||||
file_dialog.connect("dir_selected", self, "_on_output_folder_selected")
|
|
||||||
return file_dialog
|
|
||||||
|
|
||||||
|
|
||||||
func _on_output_folder_selected(path):
|
|
||||||
_output_folder = path
|
|
||||||
_out_folder_field.text = _output_folder if _output_folder != "" else _out_folder_default
|
|
||||||
_output_folder_dialog.queue_free()
|
|
||||||
@ -1,252 +0,0 @@
|
|||||||
[gd_scene load_steps=5 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/AsepriteWizard/animation_player/sprite_inspector_dock.gd" type="Script" id=1]
|
|
||||||
|
|
||||||
[sub_resource type="StyleBoxEmpty" id=1]
|
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id=2]
|
|
||||||
content_margin_left = 2.0
|
|
||||||
content_margin_right = 2.0
|
|
||||||
content_margin_top = 1.0
|
|
||||||
content_margin_bottom = 1.0
|
|
||||||
bg_color = Color( 0.25098, 0.270588, 0.32549, 1 )
|
|
||||||
|
|
||||||
[sub_resource type="StyleBoxFlat" id=3]
|
|
||||||
content_margin_left = 1.0
|
|
||||||
content_margin_right = 1.0
|
|
||||||
content_margin_top = 1.0
|
|
||||||
content_margin_bottom = 1.0
|
|
||||||
bg_color = Color( 0.2, 0.219608, 0.278431, 1 )
|
|
||||||
|
|
||||||
[node name="sprite_inspector_dock" type="PanelContainer"]
|
|
||||||
margin_right = 14.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
custom_styles/panel = SubResource( 1 )
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false,
|
|
||||||
"_editor_description_": ""
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="margin" type="MarginContainer" parent="."]
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 144.0
|
|
||||||
custom_constants/margin_top = 2
|
|
||||||
custom_constants/margin_bottom = 2
|
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="margin"]
|
|
||||||
margin_top = 2.0
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 142.0
|
|
||||||
|
|
||||||
[node name="section_title" type="PanelContainer" parent="margin/VBoxContainer"]
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 16.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
custom_styles/panel = SubResource( 2 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="title" type="Label" parent="margin/VBoxContainer/section_title"]
|
|
||||||
margin_left = 2.0
|
|
||||||
margin_top = 1.0
|
|
||||||
margin_right = 185.0
|
|
||||||
margin_bottom = 15.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
text = "Aseprite"
|
|
||||||
align = 1
|
|
||||||
|
|
||||||
[node name="animation_player" type="HBoxContainer" parent="margin/VBoxContainer"]
|
|
||||||
margin_top = 20.0
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 40.0
|
|
||||||
hint_tooltip = "AnimationPlayer node where animations should be added to."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/animation_player"]
|
|
||||||
margin_top = 3.0
|
|
||||||
margin_right = 105.0
|
|
||||||
margin_bottom = 17.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "AnimationPlayer"
|
|
||||||
|
|
||||||
[node name="options" type="OptionButton" parent="margin/VBoxContainer/animation_player"]
|
|
||||||
margin_left = 109.0
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "[empty]"
|
|
||||||
align = 1
|
|
||||||
|
|
||||||
[node name="source" type="HBoxContainer" parent="margin/VBoxContainer"]
|
|
||||||
margin_top = 44.0
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 64.0
|
|
||||||
hint_tooltip = "Location of the Aseprite (*.ase, *.aseprite) source file."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/source"]
|
|
||||||
margin_top = 3.0
|
|
||||||
margin_right = 91.0
|
|
||||||
margin_bottom = 17.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Aseprite File"
|
|
||||||
|
|
||||||
[node name="button" type="Button" parent="margin/VBoxContainer/source"]
|
|
||||||
margin_left = 95.0
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "[empty]"
|
|
||||||
clip_text = true
|
|
||||||
|
|
||||||
[node name="layer" type="HBoxContainer" parent="margin/VBoxContainer"]
|
|
||||||
margin_top = 68.0
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 88.0
|
|
||||||
hint_tooltip = "Aseprite layer to be used in the animation. By default all layers are included."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/layer"]
|
|
||||||
margin_top = 3.0
|
|
||||||
margin_right = 91.0
|
|
||||||
margin_bottom = 17.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Layer"
|
|
||||||
|
|
||||||
[node name="options" type="OptionButton" parent="margin/VBoxContainer/layer"]
|
|
||||||
margin_left = 95.0
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "[all]"
|
|
||||||
align = 1
|
|
||||||
|
|
||||||
[node name="options_title" type="PanelContainer" parent="margin/VBoxContainer"]
|
|
||||||
margin_top = 92.0
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 116.0
|
|
||||||
custom_styles/panel = SubResource( 3 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="options_title" type="ToolButton" parent="margin/VBoxContainer/options_title"]
|
|
||||||
margin_left = 1.0
|
|
||||||
margin_top = 1.0
|
|
||||||
margin_right = 186.0
|
|
||||||
margin_bottom = 23.0
|
|
||||||
custom_colors/font_color_pressed = Color( 0.8, 0.807843, 0.827451, 1 )
|
|
||||||
toggle_mode = true
|
|
||||||
text = "Options"
|
|
||||||
align = 0
|
|
||||||
|
|
||||||
[node name="options" type="VBoxContainer" parent="margin/VBoxContainer"]
|
|
||||||
visible = false
|
|
||||||
margin_top = 120.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 240.0
|
|
||||||
|
|
||||||
[node name="out_folder" type="HBoxContainer" parent="margin/VBoxContainer/options"]
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
hint_tooltip = "Location where the spritesheet file should be saved."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/options/out_folder"]
|
|
||||||
margin_top = 3.0
|
|
||||||
margin_right = 97.0
|
|
||||||
margin_bottom = 17.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Output folder"
|
|
||||||
|
|
||||||
[node name="button" type="Button" parent="margin/VBoxContainer/options/out_folder"]
|
|
||||||
margin_left = 101.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "[empty]"
|
|
||||||
clip_text = true
|
|
||||||
|
|
||||||
[node name="out_filename" type="HBoxContainer" parent="margin/VBoxContainer/options"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
hint_tooltip = "Base filename for spritesheet. In case the layer option is used, this works as a prefix to the layer name."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/options/out_filename"]
|
|
||||||
margin_top = 5.0
|
|
||||||
margin_right = 109.0
|
|
||||||
margin_bottom = 19.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Output file name"
|
|
||||||
|
|
||||||
[node name="LineEdit" type="LineEdit" parent="margin/VBoxContainer/options/out_filename"]
|
|
||||||
margin_left = 113.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
|
|
||||||
[node name="ex_pattern" type="HBoxContainer" parent="margin/VBoxContainer/options"]
|
|
||||||
margin_top = 52.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 76.0
|
|
||||||
hint_tooltip = "Exclude layers with name matching this pattern (regex)."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/options/ex_pattern"]
|
|
||||||
margin_top = 5.0
|
|
||||||
margin_right = 99.0
|
|
||||||
margin_bottom = 19.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Exclude pattern"
|
|
||||||
|
|
||||||
[node name="LineEdit" type="LineEdit" parent="margin/VBoxContainer/options/ex_pattern"]
|
|
||||||
margin_left = 103.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
|
|
||||||
[node name="visible_layers" type="HBoxContainer" parent="margin/VBoxContainer/options"]
|
|
||||||
margin_top = 80.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 120.0
|
|
||||||
hint_tooltip = "If active, layers not visible in the source file won't be included in the final image."
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="margin/VBoxContainer/options/visible_layers"]
|
|
||||||
margin_top = 13.0
|
|
||||||
margin_right = 118.0
|
|
||||||
margin_bottom = 27.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
text = "Only visible layers"
|
|
||||||
|
|
||||||
[node name="CheckButton" type="CheckButton" parent="margin/VBoxContainer/options/visible_layers"]
|
|
||||||
margin_left = 122.0
|
|
||||||
margin_right = 198.0
|
|
||||||
margin_bottom = 40.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_stretch_ratio = 2.0
|
|
||||||
|
|
||||||
[node name="import" type="Button" parent="margin/VBoxContainer"]
|
|
||||||
margin_top = 120.0
|
|
||||||
margin_right = 187.0
|
|
||||||
margin_bottom = 140.0
|
|
||||||
text = "Import"
|
|
||||||
|
|
||||||
[connection signal="item_selected" from="margin/VBoxContainer/animation_player/options" to="." method="_on_options_item_selected"]
|
|
||||||
[connection signal="pressed" from="margin/VBoxContainer/animation_player/options" to="." method="_on_options_pressed"]
|
|
||||||
[connection signal="pressed" from="margin/VBoxContainer/source/button" to="." method="_on_source_pressed"]
|
|
||||||
[connection signal="item_selected" from="margin/VBoxContainer/layer/options" to="." method="_on_layer_item_selected"]
|
|
||||||
[connection signal="pressed" from="margin/VBoxContainer/layer/options" to="." method="_on_layer_pressed"]
|
|
||||||
[connection signal="toggled" from="margin/VBoxContainer/options_title/options_title" to="." method="_on_options_title_toggled"]
|
|
||||||
[connection signal="pressed" from="margin/VBoxContainer/options/out_folder/button" to="." method="_on_out_folder_pressed"]
|
|
||||||
[connection signal="pressed" from="margin/VBoxContainer/import" to="." method="_on_import_pressed"]
|
|
||||||
@ -1,183 +0,0 @@
|
|||||||
tool
|
|
||||||
extends Reference
|
|
||||||
|
|
||||||
var _config
|
|
||||||
|
|
||||||
func init(config):
|
|
||||||
_config = config
|
|
||||||
|
|
||||||
#
|
|
||||||
# Output:
|
|
||||||
# {
|
|
||||||
# "data_file": file path to the json file
|
|
||||||
# "sprite_sheet": file path to the raw image file
|
|
||||||
# }
|
|
||||||
func export_file(file_name: String, output_folder: String, options: Dictionary) -> Dictionary:
|
|
||||||
var exception_pattern = options.get('exception_pattern', "")
|
|
||||||
var only_visible_layers = options.get('only_visible_layers', false)
|
|
||||||
var output_name = file_name if options.get('output_filename') == "" else options.get('output_filename', file_name)
|
|
||||||
var basename = _get_file_basename(output_name)
|
|
||||||
var output_dir = output_folder.replace("res://", "./")
|
|
||||||
var data_file = "%s/%s.json" % [output_dir, basename]
|
|
||||||
var sprite_sheet = "%s/%s.png" % [output_dir, basename]
|
|
||||||
var output = []
|
|
||||||
var arguments = _export_command_common_arguments(file_name, data_file, sprite_sheet)
|
|
||||||
|
|
||||||
if not only_visible_layers:
|
|
||||||
arguments.push_front("--all-layers")
|
|
||||||
|
|
||||||
_add_sheet_type_arguments(arguments, options)
|
|
||||||
|
|
||||||
_add_ignore_layer_arguments(file_name, arguments, exception_pattern)
|
|
||||||
|
|
||||||
var exit_code = _execute(arguments, output)
|
|
||||||
if exit_code != 0:
|
|
||||||
printerr('aseprite: failed to export spritesheet')
|
|
||||||
printerr(output)
|
|
||||||
return {}
|
|
||||||
|
|
||||||
return {
|
|
||||||
'data_file': data_file.replace("./", "res://"),
|
|
||||||
"sprite_sheet": sprite_sheet.replace("./", "res://")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func export_layers(file_name: String, output_folder: String, options: Dictionary) -> Array:
|
|
||||||
var exception_pattern = options.get('exception_pattern', "")
|
|
||||||
var only_visible_layers = options.get('only_visible_layers', false)
|
|
||||||
var basename = _get_file_basename(file_name)
|
|
||||||
var layers = list_layers(file_name, only_visible_layers)
|
|
||||||
var exception_regex = _compile_regex(exception_pattern)
|
|
||||||
|
|
||||||
var output = []
|
|
||||||
|
|
||||||
for layer in layers:
|
|
||||||
if layer != "" and (not exception_regex or exception_regex.search(layer) == null):
|
|
||||||
output.push_back(export_layer(file_name, layer, output_folder, options))
|
|
||||||
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
func export_layer(file_name: String, layer_name: String, output_folder: String, options: Dictionary) -> Dictionary:
|
|
||||||
var output_prefix = options.get('output_filename', "")
|
|
||||||
var output_dir = output_folder.replace("res://", "./")
|
|
||||||
var data_file = "%s/%s%s.json" % [output_dir, output_prefix, layer_name]
|
|
||||||
var sprite_sheet = "%s/%s%s.png" % [output_dir, output_prefix, layer_name]
|
|
||||||
var output = []
|
|
||||||
var arguments = _export_command_common_arguments(file_name, data_file, sprite_sheet)
|
|
||||||
arguments.push_front(layer_name)
|
|
||||||
arguments.push_front("--layer")
|
|
||||||
|
|
||||||
_add_sheet_type_arguments(arguments, options)
|
|
||||||
|
|
||||||
var exit_code = _execute(arguments, output)
|
|
||||||
if exit_code != 0:
|
|
||||||
print('aseprite: failed to export layer spritesheet')
|
|
||||||
print(output)
|
|
||||||
return {}
|
|
||||||
|
|
||||||
return {
|
|
||||||
'data_file': data_file.replace("./", "res://"),
|
|
||||||
"sprite_sheet": sprite_sheet.replace("./", "res://")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func _add_ignore_layer_arguments(file_name: String, arguments: Array, exception_pattern: String):
|
|
||||||
var layers = _get_exception_layers(file_name, exception_pattern)
|
|
||||||
if not layers.empty():
|
|
||||||
for l in layers:
|
|
||||||
arguments.push_front(l)
|
|
||||||
arguments.push_front('--ignore-layer')
|
|
||||||
|
|
||||||
func _add_sheet_type_arguments(arguments: Array, options : Dictionary):
|
|
||||||
var column_count : int = options.get("column_count", 0)
|
|
||||||
if column_count > 0:
|
|
||||||
arguments.push_back("--merge-duplicates") # Yes, this is undocumented
|
|
||||||
arguments.push_back("--sheet-columns")
|
|
||||||
arguments.push_back(column_count)
|
|
||||||
else:
|
|
||||||
arguments.push_back("--sheet-pack")
|
|
||||||
|
|
||||||
|
|
||||||
func _get_exception_layers(file_name: String, exception_pattern: String) -> Array:
|
|
||||||
var layers = list_layers(file_name)
|
|
||||||
var regex = _compile_regex(exception_pattern)
|
|
||||||
if regex == null:
|
|
||||||
return []
|
|
||||||
|
|
||||||
var exception_layers = []
|
|
||||||
for layer in layers:
|
|
||||||
if regex.search(layer) != null:
|
|
||||||
exception_layers.push_back(layer)
|
|
||||||
|
|
||||||
return exception_layers
|
|
||||||
|
|
||||||
|
|
||||||
func list_layers(file_name: String, only_visible = false) -> Array:
|
|
||||||
var output = []
|
|
||||||
var arguments = ["-b", "--list-layers", file_name]
|
|
||||||
|
|
||||||
if not only_visible:
|
|
||||||
arguments.push_front("--all-layers")
|
|
||||||
|
|
||||||
var exit_code = _execute(arguments, output)
|
|
||||||
|
|
||||||
if exit_code != 0:
|
|
||||||
printerr('aseprite: failed listing layers')
|
|
||||||
printerr(output)
|
|
||||||
return []
|
|
||||||
|
|
||||||
if output.empty():
|
|
||||||
return output
|
|
||||||
|
|
||||||
return output[0].split('\n')
|
|
||||||
|
|
||||||
|
|
||||||
func _export_command_common_arguments(source_name: String, data_path: String, spritesheet_path: String) -> Array:
|
|
||||||
return [
|
|
||||||
"-b",
|
|
||||||
"--list-tags",
|
|
||||||
"--data",
|
|
||||||
data_path,
|
|
||||||
"--format",
|
|
||||||
"json-array",
|
|
||||||
"--sheet",
|
|
||||||
spritesheet_path,
|
|
||||||
source_name
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
func _execute(arguments, output):
|
|
||||||
return OS.execute(_aseprite_command(), arguments, true, output, true)
|
|
||||||
|
|
||||||
|
|
||||||
func _aseprite_command() -> String:
|
|
||||||
return _config.get_command()
|
|
||||||
|
|
||||||
|
|
||||||
func _get_file_basename(file_path: String) -> String:
|
|
||||||
return file_path.get_file().trim_suffix('.%s' % file_path.get_extension())
|
|
||||||
|
|
||||||
|
|
||||||
func _compile_regex(pattern):
|
|
||||||
if pattern == "":
|
|
||||||
return
|
|
||||||
|
|
||||||
var rgx = RegEx.new()
|
|
||||||
if rgx.compile(pattern) == OK:
|
|
||||||
return rgx
|
|
||||||
|
|
||||||
printerr('exception regex error')
|
|
||||||
|
|
||||||
|
|
||||||
func test_command():
|
|
||||||
var exit_code = OS.execute(_aseprite_command(), ['--version'], true)
|
|
||||||
return exit_code == 0
|
|
||||||
|
|
||||||
|
|
||||||
func is_valid_spritesheet(content):
|
|
||||||
return content.has("frames") and content.has("meta") and content.meta.has('image')
|
|
||||||
|
|
||||||
|
|
||||||
func get_content_frames(content):
|
|
||||||
return content.frames if typeof(content.frames) == TYPE_ARRAY else content.frames.values()
|
|
||||||
@ -1,175 +0,0 @@
|
|||||||
tool
|
|
||||||
extends Reference
|
|
||||||
|
|
||||||
# GLOBAL CONFIGS
|
|
||||||
const CONFIG_FILE_PATH = 'user://aseprite_wizard.cfg'
|
|
||||||
const _CONFIG_SECTION_KEY = 'aseprite'
|
|
||||||
const _COMMAND_KEY = 'command'
|
|
||||||
const _IMPORTER_ENABLE_KEY = 'is_importer_enabled'
|
|
||||||
const _REMOVE_SOURCE_FILES_KEY = 'remove_source_files'
|
|
||||||
const _LOOP_ENABLED = 'loop_enabled'
|
|
||||||
const _LOOP_EXCEPTION_PREFIX = 'loop_config_prefix'
|
|
||||||
const _DEFAULT_LOOP_EX_PREFIX = '_'
|
|
||||||
const _DEFAULT_EXCLUSION_PATTERN_KEY = 'default_layer_ex_pattern'
|
|
||||||
|
|
||||||
# IMPORT CONFIGS
|
|
||||||
const _IMPORT_SECTION_KEY = 'file_locations'
|
|
||||||
const _I_LAST_SOURCE_PATH_KEY = 'source'
|
|
||||||
const _I_LAST_OUTPUT_DIR_KEY = 'output'
|
|
||||||
const _I_SHOULD_SPLIT_LAYERS_KEY = 'split_layers'
|
|
||||||
const _I_EXCEPTIONS_KEY = 'exceptions_key'
|
|
||||||
const _I_ONLY_VISIBLE_LAYERS_KEY = 'only_visible_layers'
|
|
||||||
const _I_CUSTOM_NAME_KEY = 'custom_name'
|
|
||||||
const _I_DO_NOT_CREATE_RES_KEY = 'disable_resource_creation'
|
|
||||||
|
|
||||||
# INTERFACE CONFIGS
|
|
||||||
var _icon_arrow_down: Texture
|
|
||||||
var _icon_arrow_right: Texture
|
|
||||||
|
|
||||||
var _config := ConfigFile.new()
|
|
||||||
|
|
||||||
|
|
||||||
func load_config() -> void:
|
|
||||||
_config = ConfigFile.new()
|
|
||||||
_config.load(CONFIG_FILE_PATH)
|
|
||||||
|
|
||||||
|
|
||||||
func save() -> void:
|
|
||||||
_config.save(CONFIG_FILE_PATH)
|
|
||||||
|
|
||||||
#######################################################
|
|
||||||
# GLOBAL CONFIGS
|
|
||||||
######################################################
|
|
||||||
|
|
||||||
func default_command() -> String:
|
|
||||||
return 'aseprite'
|
|
||||||
|
|
||||||
|
|
||||||
func get_command() -> String:
|
|
||||||
var command = _config.get_value(_CONFIG_SECTION_KEY, _COMMAND_KEY, "")
|
|
||||||
return command if command != "" else default_command()
|
|
||||||
|
|
||||||
|
|
||||||
func set_command(aseprite_command: String) -> void:
|
|
||||||
if aseprite_command == "":
|
|
||||||
_config.set_value(_CONFIG_SECTION_KEY, _COMMAND_KEY, default_command())
|
|
||||||
else:
|
|
||||||
_config.set_value(_CONFIG_SECTION_KEY, _COMMAND_KEY, aseprite_command)
|
|
||||||
|
|
||||||
|
|
||||||
func is_importer_enabled() -> bool:
|
|
||||||
return _config.get_value(_CONFIG_SECTION_KEY, _IMPORTER_ENABLE_KEY, false)
|
|
||||||
|
|
||||||
|
|
||||||
func set_importer_enabled(is_enabled: bool) -> void:
|
|
||||||
_config.set_value(_CONFIG_SECTION_KEY, _IMPORTER_ENABLE_KEY, is_enabled)
|
|
||||||
|
|
||||||
|
|
||||||
func should_remove_source_files() -> bool:
|
|
||||||
return _config.get_value(_CONFIG_SECTION_KEY, _REMOVE_SOURCE_FILES_KEY, true)
|
|
||||||
|
|
||||||
|
|
||||||
func set_remove_source_files(should_remove: bool) -> void:
|
|
||||||
_config.set_value(_CONFIG_SECTION_KEY, _REMOVE_SOURCE_FILES_KEY, should_remove)
|
|
||||||
|
|
||||||
|
|
||||||
func is_default_animation_loop_enabled() -> bool:
|
|
||||||
return _config.get_value(_CONFIG_SECTION_KEY, _LOOP_ENABLED, true)
|
|
||||||
|
|
||||||
|
|
||||||
func set_default_animation_loop(should_loop: bool) -> void:
|
|
||||||
_config.set_value(_CONFIG_SECTION_KEY, _LOOP_ENABLED, should_loop)
|
|
||||||
|
|
||||||
|
|
||||||
func get_animation_loop_exception_prefix() -> String:
|
|
||||||
return _config.get_value(_CONFIG_SECTION_KEY, _LOOP_EXCEPTION_PREFIX, _DEFAULT_LOOP_EX_PREFIX)
|
|
||||||
|
|
||||||
|
|
||||||
func set_animation_loop_exception_prefix(prefix: String) -> void:
|
|
||||||
_config.set_value(_CONFIG_SECTION_KEY, _LOOP_EXCEPTION_PREFIX, prefix if prefix != "" else _DEFAULT_LOOP_EX_PREFIX)
|
|
||||||
|
|
||||||
|
|
||||||
func get_default_exclusion_pattern() -> String:
|
|
||||||
return _config.get_value(_CONFIG_SECTION_KEY, _DEFAULT_EXCLUSION_PATTERN_KEY, "")
|
|
||||||
|
|
||||||
|
|
||||||
func set_default_exclusion_pattern(pattern: String) -> void:
|
|
||||||
_config.set_value(_CONFIG_SECTION_KEY, _DEFAULT_EXCLUSION_PATTERN_KEY, pattern)
|
|
||||||
|
|
||||||
|
|
||||||
#######################################################
|
|
||||||
# IMPORT CONFIGS
|
|
||||||
######################################################
|
|
||||||
func get_last_source_path() -> String:
|
|
||||||
return _config.get_value(_IMPORT_SECTION_KEY, _I_LAST_SOURCE_PATH_KEY, "")
|
|
||||||
|
|
||||||
|
|
||||||
func set_last_source_path(source_path: String) -> void:
|
|
||||||
_config.set_value(_IMPORT_SECTION_KEY, _I_LAST_SOURCE_PATH_KEY, source_path)
|
|
||||||
|
|
||||||
|
|
||||||
func get_last_output_path() -> String:
|
|
||||||
return _config.get_value(_IMPORT_SECTION_KEY, _I_LAST_OUTPUT_DIR_KEY, "")
|
|
||||||
|
|
||||||
|
|
||||||
func set_last_output_path(output_path: String) -> void:
|
|
||||||
_config.set_value(_IMPORT_SECTION_KEY, _I_LAST_OUTPUT_DIR_KEY, output_path)
|
|
||||||
|
|
||||||
|
|
||||||
func should_split_layers() -> bool:
|
|
||||||
return _config.get_value(_IMPORT_SECTION_KEY, _I_SHOULD_SPLIT_LAYERS_KEY, false)
|
|
||||||
|
|
||||||
|
|
||||||
func set_split_layers(should_split: bool) -> void:
|
|
||||||
_config.set_value(_IMPORT_SECTION_KEY, _I_SHOULD_SPLIT_LAYERS_KEY, false)
|
|
||||||
|
|
||||||
|
|
||||||
func get_exception_pattern() -> String:
|
|
||||||
return _config.get_value(_IMPORT_SECTION_KEY, _I_EXCEPTIONS_KEY, "")
|
|
||||||
|
|
||||||
|
|
||||||
func set_exception_pattern(pattern: String) -> void:
|
|
||||||
_config.set_value(_IMPORT_SECTION_KEY, _I_EXCEPTIONS_KEY, pattern)
|
|
||||||
|
|
||||||
|
|
||||||
func should_include_only_visible_layers() -> bool:
|
|
||||||
return _config.get_value(_IMPORT_SECTION_KEY, _I_ONLY_VISIBLE_LAYERS_KEY, false)
|
|
||||||
|
|
||||||
|
|
||||||
func set_include_only_visible_layers(include_only_visible: bool) -> void:
|
|
||||||
_config.set_value(_IMPORT_SECTION_KEY, _I_ONLY_VISIBLE_LAYERS_KEY, include_only_visible)
|
|
||||||
|
|
||||||
|
|
||||||
func get_last_custom_name() -> String:
|
|
||||||
return _config.get_value(_IMPORT_SECTION_KEY, _I_CUSTOM_NAME_KEY, "")
|
|
||||||
|
|
||||||
|
|
||||||
func set_custom_name(custom_name: String) -> void:
|
|
||||||
_config.set_value(_IMPORT_SECTION_KEY, _I_CUSTOM_NAME_KEY, custom_name)
|
|
||||||
|
|
||||||
|
|
||||||
func should_not_create_resource() -> bool:
|
|
||||||
return _config.get_value(_IMPORT_SECTION_KEY, _I_DO_NOT_CREATE_RES_KEY, false)
|
|
||||||
|
|
||||||
|
|
||||||
func set_do_not_create_resource(do_no_create: bool) -> void:
|
|
||||||
_config.set_value(_IMPORT_SECTION_KEY, _I_DO_NOT_CREATE_RES_KEY, do_no_create)
|
|
||||||
|
|
||||||
|
|
||||||
#######################################################
|
|
||||||
# INTERFACE CONFIGS
|
|
||||||
######################################################
|
|
||||||
func set_icon_arrow_down(icon: Texture) -> void:
|
|
||||||
_icon_arrow_down = icon
|
|
||||||
|
|
||||||
|
|
||||||
func get_icon_arrow_down() -> Texture:
|
|
||||||
return _icon_arrow_down
|
|
||||||
|
|
||||||
|
|
||||||
func set_icon_arrow_right(icon: Texture) -> void:
|
|
||||||
_icon_arrow_right = icon
|
|
||||||
|
|
||||||
|
|
||||||
func get_icon_arrow_right() -> Texture:
|
|
||||||
return _icon_arrow_right
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
tool
|
|
||||||
extends PopupPanel
|
|
||||||
|
|
||||||
signal importer_state_changed
|
|
||||||
|
|
||||||
var _config
|
|
||||||
|
|
||||||
onready var _aseprite_command_field = $MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer/aseprite_command
|
|
||||||
onready var _importer_enable_field = $MarginContainer/VBoxContainer/enable_importer
|
|
||||||
onready var _remove_source_files_field = $MarginContainer/VBoxContainer/remove_source
|
|
||||||
onready var _enable_animation_loop = $MarginContainer/VBoxContainer/loop_animations
|
|
||||||
onready var _loop_ex_prefix = $MarginContainer/VBoxContainer/loop/loop_config_prefix
|
|
||||||
onready var _layer_ex_pattern = $MarginContainer/VBoxContainer/layer_ex/ex_p_config_prefix
|
|
||||||
onready var _version_label = $MarginContainer/VBoxContainer/VBoxContainer/version_found
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
_aseprite_command_field.text = _config.get_command()
|
|
||||||
_importer_enable_field.pressed = _config.is_importer_enabled()
|
|
||||||
_remove_source_files_field.pressed = _config.should_remove_source_files()
|
|
||||||
_enable_animation_loop.pressed = _config.is_default_animation_loop_enabled()
|
|
||||||
_loop_ex_prefix.text = _config.get_animation_loop_exception_prefix()
|
|
||||||
_layer_ex_pattern.text = _config.get_default_exclusion_pattern()
|
|
||||||
_version_label.modulate.a = 0
|
|
||||||
|
|
||||||
|
|
||||||
func init(config):
|
|
||||||
_config = config
|
|
||||||
|
|
||||||
|
|
||||||
func _on_save_button_up():
|
|
||||||
_config.set_command(_aseprite_command_field.text)
|
|
||||||
|
|
||||||
if _importer_enable_field.pressed != _config.is_importer_enabled():
|
|
||||||
_config.set_importer_enabled(_importer_enable_field.pressed)
|
|
||||||
self.emit_signal("importer_state_changed")
|
|
||||||
|
|
||||||
_config.set_remove_source_files(_remove_source_files_field.pressed)
|
|
||||||
_config.set_default_animation_loop(_enable_animation_loop.pressed)
|
|
||||||
_config.set_animation_loop_exception_prefix(_loop_ex_prefix.text)
|
|
||||||
_config.set_default_exclusion_pattern(_layer_ex_pattern.text)
|
|
||||||
|
|
||||||
_config.save()
|
|
||||||
self.hide()
|
|
||||||
|
|
||||||
|
|
||||||
func _on_close_button_up():
|
|
||||||
self.hide()
|
|
||||||
|
|
||||||
|
|
||||||
func _on_test_pressed():
|
|
||||||
var output = []
|
|
||||||
if _test_command(output):
|
|
||||||
_version_label.text = "%s found." % PoolStringArray(output).join("\n").strip_edges()
|
|
||||||
else:
|
|
||||||
_version_label.text = "Command not found."
|
|
||||||
_version_label.modulate.a = 1
|
|
||||||
|
|
||||||
|
|
||||||
func _test_command(output):
|
|
||||||
var exit_code = OS.execute(_aseprite_command_field.text, ['--version'], true, output, true)
|
|
||||||
return exit_code == 0
|
|
||||||
@ -1,176 +0,0 @@
|
|||||||
[gd_scene load_steps=2 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/AsepriteWizard/config/config_dialog.gd" type="Script" id=1]
|
|
||||||
|
|
||||||
[node name="config_dialog" type="PopupPanel"]
|
|
||||||
margin_right = 400.0
|
|
||||||
margin_bottom = 250.0
|
|
||||||
rect_min_size = Vector2( 600, 250 )
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
margin_left = 4.0
|
|
||||||
margin_top = 4.0
|
|
||||||
margin_right = -4.0
|
|
||||||
margin_bottom = -4.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
custom_constants/margin_right = 40
|
|
||||||
custom_constants/margin_top = 40
|
|
||||||
custom_constants/margin_left = 40
|
|
||||||
custom_constants/margin_bottom = 40
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
|
||||||
margin_left = 40.0
|
|
||||||
margin_top = 40.0
|
|
||||||
margin_right = 552.0
|
|
||||||
margin_bottom = 420.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_vertical = 3
|
|
||||||
custom_constants/separation = 20
|
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 72.0
|
|
||||||
custom_constants/separation = 10
|
|
||||||
|
|
||||||
[node name="Aseprite Command" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer"]
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
hint_tooltip = "Define the path for Aseprite command"
|
|
||||||
mouse_filter = 1
|
|
||||||
text = "Aseprite Command Path"
|
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
|
|
||||||
[node name="aseprite_command" type="LineEdit" parent="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
|
|
||||||
margin_right = 469.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
caret_blink = true
|
|
||||||
|
|
||||||
[node name="test" type="Button" parent="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
|
|
||||||
margin_left = 473.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 24.0
|
|
||||||
text = "Test"
|
|
||||||
|
|
||||||
[node name="version_found" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer"]
|
|
||||||
modulate = Color( 1, 1, 1, 0 )
|
|
||||||
margin_top = 58.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 72.0
|
|
||||||
rect_min_size = Vector2( 300, 0 )
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
text = "Aseprite version found"
|
|
||||||
|
|
||||||
[node name="enable_importer" type="CheckBox" parent="MarginContainer/VBoxContainer"]
|
|
||||||
margin_top = 92.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 116.0
|
|
||||||
hint_tooltip = "Enable Aseprite automatic importer for files located inside the project folder."
|
|
||||||
pressed = true
|
|
||||||
text = "Enable Aseprite Importer"
|
|
||||||
|
|
||||||
[node name="remove_source" type="CheckBox" parent="MarginContainer/VBoxContainer"]
|
|
||||||
margin_top = 136.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 160.0
|
|
||||||
hint_tooltip = "removes *.json files generated during import."
|
|
||||||
text = "Remove source files"
|
|
||||||
|
|
||||||
[node name="loop_animations" type="CheckBox" parent="MarginContainer/VBoxContainer"]
|
|
||||||
margin_top = 180.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 204.0
|
|
||||||
hint_tooltip = "Default loop value for animations"
|
|
||||||
pressed = true
|
|
||||||
text = "Loop animations"
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_description_": ""
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="loop" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
|
|
||||||
margin_top = 224.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 272.0
|
|
||||||
hint_tooltip = "Animations starting with this prefix should be imported with opposite loop configuration. Prefix is removed from animation name."
|
|
||||||
custom_constants/separation = 10
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_description_": ""
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="loop_prefix_label" type="Label" parent="MarginContainer/VBoxContainer/loop"]
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
mouse_filter = 1
|
|
||||||
text = "Loop exception prefix"
|
|
||||||
|
|
||||||
[node name="loop_config_prefix" type="LineEdit" parent="MarginContainer/VBoxContainer/loop"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
text = "_"
|
|
||||||
caret_blink = true
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_description_": ""
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="layer_ex" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
|
|
||||||
margin_top = 292.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 340.0
|
|
||||||
hint_tooltip = "Exclude layers with name matching this pattern (regex). This is the default value. It can be changed during import."
|
|
||||||
custom_constants/separation = 10
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_description_": ""
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="ex_p_prefix_label" type="Label" parent="MarginContainer/VBoxContainer/layer_ex"]
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 14.0
|
|
||||||
mouse_filter = 1
|
|
||||||
text = "Default layer exclusion pattern"
|
|
||||||
|
|
||||||
[node name="ex_p_config_prefix" type="LineEdit" parent="MarginContainer/VBoxContainer/layer_ex"]
|
|
||||||
margin_top = 24.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 48.0
|
|
||||||
caret_blink = true
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_description_": ""
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="VBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
|
||||||
margin_top = 360.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 380.0
|
|
||||||
custom_constants/separation = 30
|
|
||||||
alignment = 2
|
|
||||||
|
|
||||||
[node name="close" type="Button" parent="MarginContainer/VBoxContainer/VBoxContainer2"]
|
|
||||||
margin_left = 394.0
|
|
||||||
margin_right = 441.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
text = "Close"
|
|
||||||
|
|
||||||
[node name="save" type="Button" parent="MarginContainer/VBoxContainer/VBoxContainer2"]
|
|
||||||
margin_left = 471.0
|
|
||||||
margin_right = 512.0
|
|
||||||
margin_bottom = 20.0
|
|
||||||
text = "Save"
|
|
||||||
|
|
||||||
[connection signal="pressed" from="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer/test" to="." method="_on_test_pressed"]
|
|
||||||
[connection signal="button_up" from="MarginContainer/VBoxContainer/VBoxContainer2/close" to="." method="_on_close_button_up"]
|
|
||||||
[connection signal="button_up" from="MarginContainer/VBoxContainer/VBoxContainer2/save" to="." method="_on_save_button_up"]
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
tool
|
|
||||||
extends Reference
|
|
||||||
|
|
||||||
const SUCCESS = 0
|
|
||||||
const ERR_ASEPRITE_CMD_NOT_FOUND = 1
|
|
||||||
const ERR_SOURCE_FILE_NOT_FOUND = 2
|
|
||||||
const ERR_OUTPUT_FOLDER_NOT_FOUND = 3
|
|
||||||
const ERR_ASEPRITE_EXPORT_FAILED = 4
|
|
||||||
const ERR_UNKNOWN_EXPORT_MODE = 5
|
|
||||||
const ERR_NO_VALID_LAYERS_FOUND = 6
|
|
||||||
const ERR_INVALID_ASEPRITE_SPRITESHEET = 7
|
|
||||||
|
|
||||||
|
|
||||||
static func get_error_message(code: int):
|
|
||||||
match code:
|
|
||||||
ERR_ASEPRITE_CMD_NOT_FOUND:
|
|
||||||
return "Aseprite command failed. Please, check if the right command is in your PATH or configured through \"Project > Tools > Aseprite Wizard Config\"."
|
|
||||||
ERR_SOURCE_FILE_NOT_FOUND:
|
|
||||||
return "source file does not exist"
|
|
||||||
ERR_OUTPUT_FOLDER_NOT_FOUND:
|
|
||||||
return "output location does not exist"
|
|
||||||
ERR_ASEPRITE_EXPORT_FAILED:
|
|
||||||
return "unable to import file"
|
|
||||||
ERR_INVALID_ASEPRITE_SPRITESHEET:
|
|
||||||
return "aseprite generated bad data file"
|
|
||||||
ERR_NO_VALID_LAYERS_FOUND:
|
|
||||||
return "no valid layers found"
|
|
||||||
_:
|
|
||||||
return "import failed with code %d" % code
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
tool
|
|
||||||
extends Reference
|
|
||||||
|
|
||||||
const WIZARD_CONFIG_MARKER = "aseprite_wizard_config"
|
|
||||||
const SEPARATOR = "|="
|
|
||||||
|
|
||||||
static func encode(object: Dictionary):
|
|
||||||
var text = "%s\n" % WIZARD_CONFIG_MARKER
|
|
||||||
|
|
||||||
for prop in object:
|
|
||||||
text += "%s%s%s\n" % [prop, SEPARATOR, object[prop]]
|
|
||||||
|
|
||||||
return Marshalls.utf8_to_base64(text)
|
|
||||||
|
|
||||||
|
|
||||||
static func decode(string: String):
|
|
||||||
var decoded = _decode_base64(string)
|
|
||||||
if not _is_wizard_config(decoded):
|
|
||||||
return null
|
|
||||||
|
|
||||||
var cfg = decoded.split("\n")
|
|
||||||
var config = {}
|
|
||||||
for c in cfg:
|
|
||||||
var parts = c.split(SEPARATOR, 1)
|
|
||||||
if parts.size() == 2:
|
|
||||||
config[parts[0].strip_edges()] = parts[1].strip_edges()
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
static func _decode_base64(string: String):
|
|
||||||
if string != "":
|
|
||||||
return Marshalls.base64_to_utf8(string)
|
|
||||||
return null
|
|
||||||
|
|
||||||
|
|
||||||
static func _is_wizard_config(cfg) -> bool:
|
|
||||||
return cfg != null and cfg.begins_with(WIZARD_CONFIG_MARKER)
|
|
||||||
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
[plugin]
|
|
||||||
|
|
||||||
name="Aseprite Wizard"
|
|
||||||
description="Import Aseprite files to AnimationPlayers, AnimatedSprites and SpriteFrames."
|
|
||||||
author="Vinicius Gerevini"
|
|
||||||
version="4.1.1"
|
|
||||||
script="plugin.gd"
|
|
||||||
@ -1,129 +0,0 @@
|
|||||||
tool
|
|
||||||
extends EditorPlugin
|
|
||||||
|
|
||||||
const ConfigDialog = preload('config/config_dialog.tscn')
|
|
||||||
const WizardWindow = preload("animated_sprite/ASWizardWindow.tscn")
|
|
||||||
const ImportPlugin = preload("animated_sprite/import_plugin.gd")
|
|
||||||
const AnimatedSpriteInspectorPlugin = preload("animated_sprite/inspector_plugin.gd")
|
|
||||||
const SpriteInspectorPlugin = preload("animation_player/inspector_plugin.gd")
|
|
||||||
const menu_item_name = "Aseprite Spritesheet Wizard"
|
|
||||||
const config_menu_item_name = "Aseprite Wizard Config"
|
|
||||||
|
|
||||||
var config = preload("config/config.gd").new()
|
|
||||||
var window: PanelContainer
|
|
||||||
var config_window: PopupPanel
|
|
||||||
var import_plugin : EditorImportPlugin
|
|
||||||
var sprite_inspector_plugin: EditorInspectorPlugin
|
|
||||||
var animated_sprite_inspector_plugin: EditorInspectorPlugin
|
|
||||||
|
|
||||||
var _importer_enabled = false
|
|
||||||
|
|
||||||
func _enter_tree():
|
|
||||||
_load_config()
|
|
||||||
_setup_menu_entries()
|
|
||||||
_setup_importer()
|
|
||||||
_setup_animated_sprite_inspector_plugin()
|
|
||||||
_setup_sprite_inspector_plugin()
|
|
||||||
|
|
||||||
|
|
||||||
func _exit_tree():
|
|
||||||
_remove_menu_entries()
|
|
||||||
_remove_importer()
|
|
||||||
_remove_wizard_dock()
|
|
||||||
_remove_inspector_plugins()
|
|
||||||
|
|
||||||
|
|
||||||
func _load_config():
|
|
||||||
var editor_gui = get_editor_interface().get_base_control()
|
|
||||||
config.load_config()
|
|
||||||
config.set_icon_arrow_down(editor_gui.get_icon("GuiTreeArrowDown", "EditorIcons"))
|
|
||||||
config.set_icon_arrow_right(editor_gui.get_icon("GuiTreeArrowRight", "EditorIcons"))
|
|
||||||
|
|
||||||
|
|
||||||
func _setup_menu_entries():
|
|
||||||
add_tool_menu_item(menu_item_name, self, "_open_window")
|
|
||||||
add_tool_menu_item(config_menu_item_name, self, "_open_config_dialog")
|
|
||||||
|
|
||||||
|
|
||||||
func _remove_menu_entries():
|
|
||||||
remove_tool_menu_item(menu_item_name)
|
|
||||||
remove_tool_menu_item(config_menu_item_name)
|
|
||||||
|
|
||||||
|
|
||||||
func _setup_importer():
|
|
||||||
if (config.is_importer_enabled()):
|
|
||||||
import_plugin = ImportPlugin.new()
|
|
||||||
add_import_plugin(import_plugin)
|
|
||||||
_importer_enabled = true
|
|
||||||
|
|
||||||
|
|
||||||
func _remove_importer():
|
|
||||||
if _importer_enabled:
|
|
||||||
remove_import_plugin(import_plugin)
|
|
||||||
_importer_enabled = false
|
|
||||||
|
|
||||||
|
|
||||||
func _setup_sprite_inspector_plugin():
|
|
||||||
sprite_inspector_plugin = SpriteInspectorPlugin.new()
|
|
||||||
sprite_inspector_plugin.file_system = get_editor_interface().get_resource_filesystem()
|
|
||||||
sprite_inspector_plugin.config = config
|
|
||||||
add_inspector_plugin(sprite_inspector_plugin)
|
|
||||||
|
|
||||||
|
|
||||||
func _setup_animated_sprite_inspector_plugin():
|
|
||||||
animated_sprite_inspector_plugin = AnimatedSpriteInspectorPlugin.new()
|
|
||||||
animated_sprite_inspector_plugin.file_system = get_editor_interface().get_resource_filesystem()
|
|
||||||
animated_sprite_inspector_plugin.config = config
|
|
||||||
add_inspector_plugin(animated_sprite_inspector_plugin)
|
|
||||||
|
|
||||||
|
|
||||||
func _remove_inspector_plugins():
|
|
||||||
remove_inspector_plugin(sprite_inspector_plugin)
|
|
||||||
remove_inspector_plugin(animated_sprite_inspector_plugin)
|
|
||||||
|
|
||||||
|
|
||||||
func _remove_wizard_dock():
|
|
||||||
if window:
|
|
||||||
remove_control_from_bottom_panel(window)
|
|
||||||
window.queue_free()
|
|
||||||
window = null
|
|
||||||
|
|
||||||
|
|
||||||
func _open_window(_ud):
|
|
||||||
if window:
|
|
||||||
make_bottom_panel_item_visible(window)
|
|
||||||
return
|
|
||||||
|
|
||||||
window = WizardWindow.instance()
|
|
||||||
window.init(config, get_editor_interface().get_resource_filesystem())
|
|
||||||
window.connect("close_requested", self, "_on_window_closed")
|
|
||||||
add_control_to_bottom_panel(window, "Aseprite Wizard")
|
|
||||||
make_bottom_panel_item_visible(window)
|
|
||||||
|
|
||||||
|
|
||||||
func _open_config_dialog(_ud):
|
|
||||||
if is_instance_valid(config_window):
|
|
||||||
config_window.queue_free()
|
|
||||||
|
|
||||||
config_window = ConfigDialog.instance()
|
|
||||||
config_window.init(config)
|
|
||||||
config_window.connect("importer_state_changed", self, "_on_importer_state_changed")
|
|
||||||
get_editor_interface().get_base_control().add_child(config_window)
|
|
||||||
config_window.popup_centered()
|
|
||||||
|
|
||||||
|
|
||||||
func _on_window_closed():
|
|
||||||
if window:
|
|
||||||
remove_control_from_bottom_panel(window)
|
|
||||||
window.queue_free()
|
|
||||||
window = null
|
|
||||||
|
|
||||||
|
|
||||||
func _on_importer_state_changed():
|
|
||||||
if _importer_enabled:
|
|
||||||
remove_import_plugin(import_plugin)
|
|
||||||
_importer_enabled = false
|
|
||||||
else:
|
|
||||||
import_plugin = ImportPlugin.new()
|
|
||||||
add_import_plugin(import_plugin)
|
|
||||||
_importer_enabled = true
|
|
||||||
@ -44,17 +44,16 @@ points = PoolVector2Array( 16, 16, 0, 16, 0, 0, 16, 0 )
|
|||||||
0/z_index = 0
|
0/z_index = 0
|
||||||
|
|
||||||
[node name="LevelTemplate" type="Node2D"]
|
[node name="LevelTemplate" type="Node2D"]
|
||||||
position = Vector2( 1, 0 )
|
|
||||||
__meta__ = {
|
__meta__ = {
|
||||||
"_edit_horizontal_guides_": [ 464.0 ],
|
"_edit_horizontal_guides_": [ 464.0 ],
|
||||||
"_edit_vertical_guides_": [ 2880.0 ]
|
"_edit_vertical_guides_": [ 2880.0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[node name="UserInterface" parent="." instance=ExtResource( 7 )]
|
||||||
|
|
||||||
[node name="Simple Background" parent="." instance=ExtResource( 4 )]
|
[node name="Simple Background" parent="." instance=ExtResource( 4 )]
|
||||||
layer = -1
|
layer = -1
|
||||||
|
|
||||||
[node name="UserInterface" parent="." instance=ExtResource( 7 )]
|
|
||||||
|
|
||||||
[node name="TileMap" type="TileMap" parent="."]
|
[node name="TileMap" type="TileMap" parent="."]
|
||||||
tile_set = SubResource( 4 )
|
tile_set = SubResource( 4 )
|
||||||
cell_size = Vector2( 16, 16 )
|
cell_size = Vector2( 16, 16 )
|
||||||
@ -69,7 +68,7 @@ tile_data = PoolIntArray( 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0,
|
|||||||
position = Vector2( 50.7867, 604.063 )
|
position = Vector2( 50.7867, 604.063 )
|
||||||
|
|
||||||
[node name="Spring4" parent="." instance=ExtResource( 3 )]
|
[node name="Spring4" parent="." instance=ExtResource( 3 )]
|
||||||
position = Vector2( 159, 600 )
|
position = Vector2( 170, 600.198 )
|
||||||
scale = Vector2( 1.88002, 1 )
|
scale = Vector2( 1.88002, 1 )
|
||||||
|
|
||||||
[node name="Track" parent="." instance=ExtResource( 5 )]
|
[node name="Track" parent="." instance=ExtResource( 5 )]
|
||||||
@ -80,7 +79,7 @@ scale = Vector2( 2.83999, 0.56 )
|
|||||||
position = Vector2( 25.0812, 0 )
|
position = Vector2( 25.0812, 0 )
|
||||||
|
|
||||||
[node name="Turret" parent="." instance=ExtResource( 6 )]
|
[node name="Turret" parent="." instance=ExtResource( 6 )]
|
||||||
position = Vector2( 479, 464 )
|
position = Vector2( 479, 466 )
|
||||||
scale = Vector2( 0.4, 0.4 )
|
scale = Vector2( 0.4, 0.4 )
|
||||||
|
|
||||||
[editable path="Spring4"]
|
[editable path="Spring4"]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user