First commit 🎉
This commit is contained in:
commit
43ea213f9b
728 changed files with 37080 additions and 0 deletions
|
@ -0,0 +1,94 @@
|
|||
@tool
|
||||
extends HBoxContainer
|
||||
|
||||
signal tag_state_changed
|
||||
|
||||
const RESULT_CODE = preload("res://addons/popochiu/editor/config/result_codes.gd")
|
||||
|
||||
var _anim_tag_state: Dictionary = {}
|
||||
|
||||
@onready var tag_name_label = $HBoxContainer/TagName
|
||||
@onready var import_toggle = $Panel/HBoxContainer/Import
|
||||
@onready var loops_toggle = $Panel/HBoxContainer/Loops
|
||||
@onready var separator = $Panel/HBoxContainer/Separator
|
||||
@onready var visible_toggle = $Panel/HBoxContainer/Visible
|
||||
@onready var clickable_toggle = $Panel/HBoxContainer/Clickable
|
||||
|
||||
|
||||
#region Godot ######################################################################################
|
||||
func _ready():
|
||||
# Common toggle icons
|
||||
import_toggle.icon = get_theme_icon('Load', 'EditorIcons')
|
||||
loops_toggle.icon = get_theme_icon('Loop', 'EditorIcons')
|
||||
# Room-related toggle icons
|
||||
visible_toggle.icon = get_theme_icon('GuiVisibilityVisible', 'EditorIcons')
|
||||
clickable_toggle.icon = get_theme_icon('ToolSelect', 'EditorIcons')
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public #####################################################################################
|
||||
func init(tag_cfg: Dictionary):
|
||||
if tag_cfg.tag_name == null or tag_cfg.tag_name == "":
|
||||
printerr(RESULT_CODE.get_error_message(RESULT_CODE.ERR_UNNAMED_TAG_DETECTED))
|
||||
return false
|
||||
|
||||
_anim_tag_state = _load_default_tag_state()
|
||||
_anim_tag_state.merge(tag_cfg, true)
|
||||
_setup_scene()
|
||||
|
||||
func show_prop_buttons():
|
||||
separator.visible = true
|
||||
visible_toggle.visible = true
|
||||
clickable_toggle.visible = true
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region SetGet #####################################################################################
|
||||
func get_cfg() -> Dictionary:
|
||||
return _anim_tag_state
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private ####################################################################################
|
||||
func _setup_scene():
|
||||
import_toggle.button_pressed = _anim_tag_state.import
|
||||
loops_toggle.button_pressed = _anim_tag_state.loops
|
||||
tag_name_label.text = _anim_tag_state.tag_name
|
||||
visible_toggle.button_pressed = _anim_tag_state.prop_visible
|
||||
clickable_toggle.button_pressed = _anim_tag_state.prop_clickable
|
||||
emit_signal("tag_state_changed")
|
||||
|
||||
|
||||
func _load_default_tag_state() -> Dictionary:
|
||||
return {
|
||||
"tag_name": "",
|
||||
"import": PopochiuConfig.is_default_animation_import_enabled(),
|
||||
"loops": PopochiuConfig.is_default_animation_loop_enabled(),
|
||||
"prop_visible": PopochiuConfig.is_default_animation_prop_visible(),
|
||||
"prop_clickable": PopochiuConfig.is_default_animation_prop_clickable(),
|
||||
}
|
||||
|
||||
|
||||
func _on_import_toggled(button_pressed):
|
||||
_anim_tag_state.import = button_pressed
|
||||
emit_signal("tag_state_changed")
|
||||
|
||||
|
||||
func _on_loops_toggled(button_pressed):
|
||||
_anim_tag_state.loops = button_pressed
|
||||
emit_signal("tag_state_changed")
|
||||
|
||||
|
||||
func _on_visible_toggled(button_pressed):
|
||||
_anim_tag_state.prop_visible = button_pressed
|
||||
emit_signal("tag_state_changed")
|
||||
|
||||
func _on_clickable_toggled(button_pressed):
|
||||
_anim_tag_state.prop_clickable = button_pressed
|
||||
emit_signal("tag_state_changed")
|
||||
|
||||
|
||||
#endregion
|
|
@ -0,0 +1 @@
|
|||
uid://krf8u35pkjn3
|
|
@ -0,0 +1,94 @@
|
|||
[gd_scene load_steps=6 format=3 uid="uid://rphyltbm12m4"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/popochiu/editor/importers/aseprite/docks/animation_tag_row.gd" id="1"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_77wem"]
|
||||
|
||||
[sub_resource type="Image" id="Image_vdhps"]
|
||||
data = {
|
||||
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||
"format": "RGBA8",
|
||||
"height": 16,
|
||||
"mipmaps": false,
|
||||
"width": 16
|
||||
}
|
||||
|
||||
[sub_resource type="ImageTexture" id="ImageTexture_c80ss"]
|
||||
image = SubResource("Image_vdhps")
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_sd1l8"]
|
||||
|
||||
[node name="AnimationTagRow" type="HBoxContainer"]
|
||||
offset_right = 320.0
|
||||
offset_bottom = 20.0
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="TagName" type="Label" parent="HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Tag Name"
|
||||
|
||||
[node name="Panel" type="Panel" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_styles/panel = SubResource("StyleBoxEmpty_77wem")
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Panel"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -60.0
|
||||
offset_bottom = 20.0
|
||||
grow_horizontal = 0
|
||||
|
||||
[node name="Visible" type="Button" parent="Panel/HBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 3
|
||||
tooltip_text = "This prop will be visible"
|
||||
toggle_mode = true
|
||||
icon = SubResource("ImageTexture_c80ss")
|
||||
flat = true
|
||||
|
||||
[node name="Clickable" type="Button" parent="Panel/HBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 3
|
||||
tooltip_text = "This prop will be clickable"
|
||||
toggle_mode = true
|
||||
icon = SubResource("ImageTexture_c80ss")
|
||||
flat = true
|
||||
|
||||
[node name="Separator" type="Panel" parent="Panel/HBoxContainer"]
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(1, 0)
|
||||
layout_mode = 2
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_sd1l8")
|
||||
|
||||
[node name="Import" type="Button" parent="Panel/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 3
|
||||
tooltip_text = "Import this animation"
|
||||
toggle_mode = true
|
||||
icon = SubResource("ImageTexture_c80ss")
|
||||
flat = true
|
||||
|
||||
[node name="Loops" type="Button" parent="Panel/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 3
|
||||
tooltip_text = "Set animation as looping"
|
||||
toggle_mode = true
|
||||
icon = SubResource("ImageTexture_c80ss")
|
||||
flat = true
|
||||
|
||||
[connection signal="toggled" from="Panel/HBoxContainer/Visible" to="." method="_on_visible_toggled"]
|
||||
[connection signal="toggled" from="Panel/HBoxContainer/Clickable" to="." method="_on_clickable_toggled"]
|
||||
[connection signal="toggled" from="Panel/HBoxContainer/Import" to="." method="_on_import_toggled"]
|
||||
[connection signal="toggled" from="Panel/HBoxContainer/Loops" to="." method="_on_loops_toggled"]
|
|
@ -0,0 +1,429 @@
|
|||
@tool
|
||||
extends PanelContainer
|
||||
|
||||
# TODO: review coding standards for those constants
|
||||
const RESULT_CODE = preload("res://addons/popochiu/editor/config/result_codes.gd")
|
||||
const LOCAL_OBJ_CONFIG = preload("res://addons/popochiu/editor/config/local_obj_config.gd")
|
||||
# TODO: this can be specialized, even if for a two buttons... ?
|
||||
const AnimationTagRow =\
|
||||
preload("res://addons/popochiu/editor/importers/aseprite/docks/animation_tag_row.gd")
|
||||
|
||||
var scene: Node
|
||||
var target_node: Node
|
||||
var file_system: EditorFileSystem
|
||||
|
||||
# ---- External logic
|
||||
var _animation_tag_row_scene: PackedScene =\
|
||||
preload("res://addons/popochiu/editor/importers/aseprite/docks/animation_tag_row.tscn")
|
||||
var _aseprite = preload("../aseprite_controller.gd").new() ## TODO: should be absolute?
|
||||
# ---- References for children scripts
|
||||
var _root_node: Node
|
||||
var _options: Dictionary
|
||||
# ---- Importer parameters variables
|
||||
var _source: String = ""
|
||||
var _tags_cache: Array = []
|
||||
var _file_dialog_aseprite: FileDialog
|
||||
var _output_folder_dialog: FileDialog
|
||||
var _importing := false
|
||||
var _output_folder := ""
|
||||
var _out_folder_default := "[Same as scene]"
|
||||
|
||||
|
||||
#region Godot ######################################################################################
|
||||
func _ready():
|
||||
_set_elements_styles()
|
||||
|
||||
if not PopochiuEditorConfig.aseprite_importer_enabled():
|
||||
_show_info()
|
||||
return
|
||||
|
||||
# Check access to Aseprite executable
|
||||
var result = _check_aseprite()
|
||||
if result == RESULT_CODE.SUCCESS:
|
||||
_show_importer()
|
||||
else:
|
||||
PopochiuUtils.print_error(RESULT_CODE.get_error_message(result))
|
||||
_show_warning()
|
||||
|
||||
# Load inspector dock configuration from node
|
||||
var cfg = LOCAL_OBJ_CONFIG.load_config(target_node)
|
||||
if cfg == null:
|
||||
_load_default_config()
|
||||
_set_options_visible(true)
|
||||
else:
|
||||
_load_config(cfg)
|
||||
_set_tags_visible(cfg.get("tags_exp"))
|
||||
_set_options_visible(cfg.get("op_exp"))
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private ####################################################################################
|
||||
func _check_aseprite() -> int:
|
||||
if not _aseprite.check_command_path():
|
||||
return RESULT_CODE.ERR_ASEPRITE_CMD_NOT_FULL_PATH
|
||||
|
||||
if not _aseprite.test_command():
|
||||
return RESULT_CODE.ERR_ASEPRITE_CMD_NOT_FOUND
|
||||
|
||||
return RESULT_CODE.SUCCESS
|
||||
|
||||
|
||||
func _list_tags(file: String):
|
||||
if not _aseprite.check_command_path():
|
||||
return RESULT_CODE.ERR_ASEPRITE_CMD_NOT_FULL_PATH
|
||||
if not _aseprite.test_command():
|
||||
return RESULT_CODE.ERR_ASEPRITE_CMD_NOT_FOUND
|
||||
return _aseprite.list_tags(file)
|
||||
|
||||
|
||||
## TODO: Currently unused. keeping this as reference
|
||||
## to populate a checkable list of layers
|
||||
func _list_layers(file: String, only_visibles = false):
|
||||
if not _aseprite.check_command_path():
|
||||
return RESULT_CODE.ERR_ASEPRITE_CMD_NOT_FULL_PATH
|
||||
if not _aseprite.test_command():
|
||||
return RESULT_CODE.ERR_ASEPRITE_CMD_NOT_FOUND
|
||||
return _aseprite.list_layers(file, only_visibles)
|
||||
|
||||
|
||||
func _load_config(cfg):
|
||||
if cfg.has("source"):
|
||||
_set_source(cfg.source)
|
||||
|
||||
_output_folder = cfg.get("o_folder", "")
|
||||
get_node("%OutFolderButton").text = (
|
||||
_output_folder if _output_folder != "" else _out_folder_default
|
||||
)
|
||||
get_node("%OutFileName").text = cfg.get("o_name", "")
|
||||
get_node("%VisibleLayersCheckButton").set_pressed_no_signal(
|
||||
cfg.get("only_visible_layers", false)
|
||||
)
|
||||
get_node("%WipeOldAnimationsCheckButton").set_pressed_no_signal(
|
||||
cfg.get("wipe_old_anims", false)
|
||||
)
|
||||
|
||||
_set_tags_visible(cfg.get("tags_exp", false))
|
||||
_set_options_visible(cfg.get("op_exp", false))
|
||||
_populate_tags(cfg.get("tags", []))
|
||||
|
||||
|
||||
func _save_config():
|
||||
_update_tags_cache()
|
||||
|
||||
var cfg := {
|
||||
"source": _source,
|
||||
"tags": _tags_cache,
|
||||
"tags_exp": get_node("%Tags").visible,
|
||||
"op_exp": get_node("%Options").visible,
|
||||
"o_folder": _output_folder,
|
||||
"o_name": get_node("%OutFileName").text,
|
||||
"only_visible_layers": get_node("%VisibleLayersCheckButton").is_pressed(),
|
||||
"wipe_old_anims": get_node("%WipeOldAnimationsCheckButton").is_pressed(),
|
||||
}
|
||||
|
||||
LOCAL_OBJ_CONFIG.save_config(target_node, cfg)
|
||||
|
||||
|
||||
func _load_default_config():
|
||||
# Reset variables
|
||||
_source = ""
|
||||
_tags_cache = []
|
||||
_output_folder = ""
|
||||
|
||||
# Empty tags list
|
||||
_empty_tags_container()
|
||||
|
||||
# Reset inspector fields
|
||||
get_node("%SourceButton").text = "[empty]"
|
||||
get_node("%SourceButton").tooltip_text = ""
|
||||
get_node("%OutFolderButton").text = "[empty]"
|
||||
get_node("%OutFileName").clear()
|
||||
get_node("%VisibleLayersCheckButton").set_pressed_no_signal(false)
|
||||
get_node("%WipeOldAnimationsCheckButton").set_pressed_no_signal(
|
||||
PopochiuConfig.is_default_wipe_old_anims_enabled()
|
||||
)
|
||||
|
||||
|
||||
func _set_source(source):
|
||||
_source = source
|
||||
get_node("%SourceButton").text = _source
|
||||
get_node("%SourceButton").tooltip_text = _source
|
||||
|
||||
|
||||
func _on_source_pressed():
|
||||
_open_source_dialog()
|
||||
|
||||
|
||||
func _on_aseprite_file_selected(path):
|
||||
_set_source(ProjectSettings.localize_path(path))
|
||||
_populate_tags(_get_tags_from_source())
|
||||
_save_config()
|
||||
_file_dialog_aseprite.queue_free()
|
||||
|
||||
|
||||
func _on_rescan_pressed():
|
||||
_populate_tags(\
|
||||
_merge_with_cache(_get_tags_from_source())\
|
||||
)
|
||||
_save_config()
|
||||
|
||||
|
||||
func _on_import_pressed():
|
||||
if _importing:
|
||||
return
|
||||
|
||||
_importing = true
|
||||
_root_node = get_tree().get_edited_scene_root()
|
||||
|
||||
if _source == "":
|
||||
_show_message("Aseprite file not selected")
|
||||
_importing = false
|
||||
return
|
||||
|
||||
_options = {
|
||||
"source": ProjectSettings.globalize_path(_source),
|
||||
"tags": _tags_cache,
|
||||
"output_folder": (
|
||||
_output_folder if _output_folder != "" else _root_node.scene_file_path.get_base_dir()
|
||||
),
|
||||
"output_filename": get_node("%OutFileName").text,
|
||||
"only_visible_layers": get_node("%VisibleLayersCheckButton").is_pressed(),
|
||||
"wipe_old_animations": get_node("%WipeOldAnimationsCheckButton").is_pressed(),
|
||||
}
|
||||
|
||||
_save_config()
|
||||
|
||||
|
||||
func _on_reset_pressed():
|
||||
var _confirmation_dialog = _show_confirmation(\
|
||||
"This will reset the importer preferences." + \
|
||||
"This cannot be undone! Are you sure?", "Confirmation required!")
|
||||
_confirmation_dialog.get_ok_button().connect("pressed", Callable(self, "_reset_prefs_metadata"))
|
||||
|
||||
|
||||
func _reset_prefs_metadata():
|
||||
if target_node.has_meta(LOCAL_OBJ_CONFIG.LOCAL_OBJ_CONFIG_META_NAME):
|
||||
target_node.remove_meta(LOCAL_OBJ_CONFIG.LOCAL_OBJ_CONFIG_META_NAME)
|
||||
_load_default_config()
|
||||
notify_property_list_changed()
|
||||
|
||||
|
||||
func _open_source_dialog():
|
||||
_file_dialog_aseprite = _create_aseprite_file_selection()
|
||||
get_parent().add_child(_file_dialog_aseprite)
|
||||
if _source != "":
|
||||
_file_dialog_aseprite.set_current_dir(
|
||||
ProjectSettings.globalize_path(
|
||||
_source.get_base_dir()
|
||||
)
|
||||
)
|
||||
_file_dialog_aseprite.popup_centered_ratio()
|
||||
|
||||
|
||||
func _create_aseprite_file_selection():
|
||||
var file_dialog = FileDialog.new()
|
||||
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
|
||||
file_dialog.access = FileDialog.ACCESS_FILESYSTEM
|
||||
file_dialog.title = "Select Aseprite animation file"
|
||||
file_dialog.connect("file_selected", Callable(self, "_on_aseprite_file_selected"))
|
||||
file_dialog.set_filters(PackedStringArray(["*.ase","*.aseprite"]))
|
||||
return file_dialog
|
||||
|
||||
|
||||
func _populate_tags(tags: Array):
|
||||
## reset tags container
|
||||
_empty_tags_container()
|
||||
|
||||
# Add each tag found
|
||||
for t in tags:
|
||||
if t.tag_name == "":
|
||||
continue
|
||||
|
||||
var tag_row: AnimationTagRow = _animation_tag_row_scene.instantiate()
|
||||
get_node("%Tags").add_child(tag_row)
|
||||
tag_row.init(t)
|
||||
tag_row.connect("tag_state_changed", Callable(self, "_save_config"))
|
||||
_customize_tag_ui(tag_row)
|
||||
# Invoke customization hook implementable in child classes
|
||||
_update_tags_cache()
|
||||
|
||||
|
||||
func _customize_tag_ui(tagrow: AnimationTagRow):
|
||||
## This can be implemented by child classes if necessary
|
||||
pass
|
||||
|
||||
|
||||
func _empty_tags_container():
|
||||
# Clean the inspector tags container empty
|
||||
for tl in get_node("%Tags").get_children():
|
||||
get_node("%Tags").remove_child(tl)
|
||||
tl.queue_free()
|
||||
|
||||
|
||||
func _update_tags_cache():
|
||||
_tags_cache = _get_tags_from_ui()
|
||||
|
||||
|
||||
func _merge_with_cache(tags: Array) -> Array:
|
||||
var tags_cache_index = {}
|
||||
var result = []
|
||||
for t in _tags_cache:
|
||||
tags_cache_index[t.tag_name] = t
|
||||
|
||||
for i in tags.size():
|
||||
result.push_back(
|
||||
tags_cache_index[tags[i].tag_name]
|
||||
if tags_cache_index.has(tags[i].tag_name)
|
||||
else tags[i]
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
func _get_tags_from_ui() -> Array:
|
||||
var tags_list = []
|
||||
for tag_row in get_node("%Tags").get_children():
|
||||
var tag_row_cfg = tag_row.get_cfg()
|
||||
if tag_row_cfg.tag_name == "":
|
||||
continue
|
||||
tags_list.push_back(tag_row_cfg)
|
||||
return tags_list
|
||||
|
||||
|
||||
func _get_tags_from_source() -> Array:
|
||||
var tags_found = _list_tags(ProjectSettings.globalize_path(_source))
|
||||
if typeof(tags_found) == TYPE_INT:
|
||||
PopochiuUtils.print_error(RESULT_CODE.get_error_message(tags_found))
|
||||
return []
|
||||
var tags_list = []
|
||||
for t in tags_found:
|
||||
if t == "":
|
||||
continue
|
||||
tags_list.push_back({
|
||||
tag_name = t
|
||||
})
|
||||
return tags_list
|
||||
|
||||
|
||||
func _show_message(
|
||||
message: String, title: String = "", object: Object = null, method := ""
|
||||
):
|
||||
var warning_dialog = AcceptDialog.new()
|
||||
|
||||
if title != "":
|
||||
warning_dialog.title = title
|
||||
|
||||
warning_dialog.dialog_text = message
|
||||
warning_dialog.popup_window = true
|
||||
|
||||
var callback := Callable(warning_dialog, "queue_free")
|
||||
|
||||
if is_instance_valid(object) and not method.is_empty():
|
||||
callback = func():
|
||||
object.call(method)
|
||||
|
||||
warning_dialog.confirmed.connect(callback)
|
||||
warning_dialog.close_requested.connect(callback)
|
||||
|
||||
PopochiuEditorHelper.show_dialog(warning_dialog)
|
||||
|
||||
|
||||
func _show_confirmation(message: String, title: String = ""):
|
||||
var _confirmation_dialog = ConfirmationDialog.new()
|
||||
get_parent().add_child(_confirmation_dialog)
|
||||
if title != "":
|
||||
_confirmation_dialog.title = title
|
||||
_confirmation_dialog.dialog_text = message
|
||||
_confirmation_dialog.popup_centered()
|
||||
_confirmation_dialog.connect("close_requested", Callable(_confirmation_dialog, "queue_free"))
|
||||
return _confirmation_dialog
|
||||
|
||||
|
||||
func _on_options_title_toggled(button_pressed):
|
||||
_set_options_visible(button_pressed)
|
||||
_save_config()
|
||||
|
||||
|
||||
func _set_options_visible(is_visible):
|
||||
get_node("%Options").visible = is_visible
|
||||
get_node("%OptionsTitle").icon = (
|
||||
PopochiuEditorConfig.get_icon(PopochiuEditorConfig.Icons.EXPANDED) if is_visible
|
||||
else PopochiuEditorConfig.get_icon(PopochiuEditorConfig.Icons.COLLAPSED)
|
||||
)
|
||||
|
||||
func _on_tags_title_toggled(button_pressed: bool) -> void:
|
||||
_set_tags_visible(button_pressed)
|
||||
_save_config()
|
||||
|
||||
|
||||
func _set_tags_visible(is_visible: bool) -> void:
|
||||
get_node("%Tags").visible = is_visible
|
||||
get_node("%TagsTitle").icon = (
|
||||
PopochiuEditorConfig.get_icon(PopochiuEditorConfig.Icons.EXPANDED) if is_visible
|
||||
else PopochiuEditorConfig.get_icon(PopochiuEditorConfig.Icons.COLLAPSED)
|
||||
)
|
||||
|
||||
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.file_mode = FileDialog.FILE_MODE_OPEN_DIR
|
||||
file_dialog.access = FileDialog.ACCESS_RESOURCES
|
||||
file_dialog.title = "Select destination folder"
|
||||
file_dialog.connect("dir_selected", Callable(self, "_on_output_folder_selected"))
|
||||
return file_dialog
|
||||
|
||||
|
||||
func _on_output_folder_selected(path):
|
||||
_output_folder = path
|
||||
get_node("%OutFolderButton").text = (
|
||||
_output_folder if _output_folder != "" else _out_folder_default
|
||||
)
|
||||
_output_folder_dialog.queue_free()
|
||||
_save_config()
|
||||
|
||||
|
||||
func _set_elements_styles():
|
||||
# Set sections title colors according to current theme
|
||||
var section_color = get_theme_color("prop_section", "Editor")
|
||||
var section_style = StyleBoxFlat.new()
|
||||
section_style.set_bg_color(section_color)
|
||||
get_node("%TagsTitleBar").set("theme_override_styles/panel", section_style)
|
||||
get_node("%OptionsTitleBar").set("theme_override_styles/panel", section_style)
|
||||
|
||||
# Set style of warning panel
|
||||
get_node("%WarningPanel").add_theme_stylebox_override(
|
||||
"panel",
|
||||
get_node("%WarningPanel").get_theme_stylebox("sub_inspector_bg11", "Editor")
|
||||
)
|
||||
get_node("%WarningLabel").add_theme_color_override("font_color", Color("c46c71"))
|
||||
|
||||
|
||||
func _show_info():
|
||||
get_node("%Info").visible = true
|
||||
get_node("%Warning").visible = false
|
||||
get_node("%Importer").visible = false
|
||||
|
||||
|
||||
func _show_warning():
|
||||
get_node("%Info").visible = false
|
||||
get_node("%Warning").visible = true
|
||||
get_node("%Importer").visible = false
|
||||
|
||||
|
||||
func _show_importer():
|
||||
get_node("%Info").visible = false
|
||||
get_node("%Warning").visible = false
|
||||
get_node("%Importer").visible = true
|
||||
|
||||
# TODO: Introduce layer selection list, more or less as tags
|
||||
|
||||
|
||||
#endregion
|
|
@ -0,0 +1 @@
|
|||
uid://c5o55inhq2abl
|
|
@ -0,0 +1,225 @@
|
|||
[gd_scene load_steps=4 format=3 uid="uid://bcanby6n3eahm"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="1"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_wwoxk"]
|
||||
bg_color = Color(0, 0, 0, 1)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ctsm1"]
|
||||
content_margin_left = 4.0
|
||||
content_margin_top = 4.0
|
||||
content_margin_right = 4.0
|
||||
content_margin_bottom = 4.0
|
||||
bg_color = Color(1, 0.364706, 0.364706, 1)
|
||||
draw_center = false
|
||||
corner_detail = 1
|
||||
|
||||
[node name="AsepriteImporterInspectorDock" type="PanelContainer"]
|
||||
offset_right = 14.0
|
||||
offset_bottom = 14.0
|
||||
theme_override_styles/panel = SubResource("1")
|
||||
|
||||
[node name="Margin" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_top = 2
|
||||
theme_override_constants/margin_bottom = 2
|
||||
|
||||
[node name="Importer" type="VBoxContainer" parent="Margin"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Source" type="HBoxContainer" parent="Margin/Importer"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Location of the Aseprite (*.ase, *.aseprite) source file."
|
||||
|
||||
[node name="Label" type="Label" parent="Margin/Importer/Source"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
text = "Aseprite File"
|
||||
|
||||
[node name="SourceButton" type="Button" parent="Margin/Importer/Source"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
text = "[empty]"
|
||||
clip_text = true
|
||||
|
||||
[node name="RescanButton" type="Button" parent="Margin/Importer/Source"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Rescan"
|
||||
|
||||
[node name="TagsTitleBar" type="PanelContainer" parent="Margin/Importer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_wwoxk")
|
||||
|
||||
[node name="TagsTitle" type="Button" parent="Margin/Importer/TagsTitleBar"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_pressed_color = Color(0.8, 0.807843, 0.827451, 1)
|
||||
toggle_mode = true
|
||||
text = "Animation tags"
|
||||
|
||||
[node name="Tags" type="VBoxContainer" parent="Margin/Importer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="OptionsTitleBar" type="PanelContainer" parent="Margin/Importer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_wwoxk")
|
||||
|
||||
[node name="OptionsTitle" type="Button" parent="Margin/Importer/OptionsTitleBar"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_pressed_color = Color(0.8, 0.807843, 0.827451, 1)
|
||||
toggle_mode = true
|
||||
text = "Options"
|
||||
|
||||
[node name="Options" type="VBoxContainer" parent="Margin/Importer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="OutFolder" type="HBoxContainer" parent="Margin/Importer/Options"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Location where the spritesheet file should be saved."
|
||||
|
||||
[node name="Label" type="Label" parent="Margin/Importer/Options/OutFolder"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
text = "Output folder"
|
||||
|
||||
[node name="OutFolderButton" type="Button" parent="Margin/Importer/Options/OutFolder"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
text = "[empty]"
|
||||
clip_text = true
|
||||
|
||||
[node name="OutFile" type="HBoxContainer" parent="Margin/Importer/Options"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "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/Importer/Options/OutFile"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
text = "Output file name"
|
||||
|
||||
[node name="OutFileName" type="LineEdit" parent="Margin/Importer/Options/OutFile"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
|
||||
[node name="VisibleLayers" type="HBoxContainer" parent="Margin/Importer/Options"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "If active, layers not visible in the source file won't be included in the final image."
|
||||
|
||||
[node name="Label" type="Label" parent="Margin/Importer/Options/VisibleLayers"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
text = "Only visible layers"
|
||||
|
||||
[node name="VisibleLayersCheckButton" type="CheckButton" parent="Margin/Importer/Options/VisibleLayers"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
|
||||
[node name="WipeOldAnimations" type="HBoxContainer" parent="Margin/Importer/Options"]
|
||||
layout_mode = 2
|
||||
tooltip_text = "If active, layers not visible in the source file won't be included in the final image."
|
||||
|
||||
[node name="Label" type="Label" parent="Margin/Importer/Options/WipeOldAnimations"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
tooltip_text = "Set this to OFF if you want to add new animations on top of old ones. Anims with same name will be updated."
|
||||
mouse_filter = 0
|
||||
text = "Wipe old animations"
|
||||
|
||||
[node name="WipeOldAnimationsCheckButton" type="CheckButton" parent="Margin/Importer/Options/WipeOldAnimations"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
|
||||
[node name="Import" type="Button" parent="Margin/Importer"]
|
||||
layout_mode = 2
|
||||
text = "Import"
|
||||
|
||||
[node name="Reset" type="Button" parent="Margin/Importer"]
|
||||
layout_mode = 2
|
||||
text = "Reset Preferences"
|
||||
|
||||
[node name="Warning" type="VBoxContainer" parent="Margin"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Margin/Warning"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="WarningPanel" type="Panel" parent="Margin/Warning/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(222, 50)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ctsm1")
|
||||
|
||||
[node name="WarningLabel" type="Label" parent="Margin/Warning/HBoxContainer/WarningPanel"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 42)
|
||||
layout_mode = 0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 6
|
||||
theme_override_colors/font_color = Color(0.768627, 0.423529, 0.443137, 1)
|
||||
text = "Error loading Aseprite Importer!
|
||||
Check Output panel for details."
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="Info" type="VBoxContainer" parent="Margin"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Margin/Info"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="InfoPanel" type="Panel" parent="Margin/Info/HBoxContainer"]
|
||||
custom_minimum_size = Vector2(222, 50)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ctsm1")
|
||||
|
||||
[node name="InfoLabel" type="Label" parent="Margin/Info/HBoxContainer/InfoPanel"]
|
||||
custom_minimum_size = Vector2(0, 42)
|
||||
layout_mode = 0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 6
|
||||
text = "Aseprite Importer disabled.
|
||||
Can be enabled in Editor Settings."
|
||||
|
||||
[connection signal="pressed" from="Margin/Importer/Source/SourceButton" to="." method="_on_source_pressed"]
|
||||
[connection signal="pressed" from="Margin/Importer/Source/RescanButton" to="." method="_on_rescan_pressed"]
|
||||
[connection signal="toggled" from="Margin/Importer/TagsTitleBar/TagsTitle" to="." method="_on_tags_title_toggled"]
|
||||
[connection signal="toggled" from="Margin/Importer/OptionsTitleBar/OptionsTitle" to="." method="_on_options_title_toggled"]
|
||||
[connection signal="pressed" from="Margin/Importer/Options/OutFolder/OutFolderButton" to="." method="_on_out_folder_pressed"]
|
||||
[connection signal="focus_exited" from="Margin/Importer/Options/OutFile/OutFileName" to="." method="_save_config"]
|
||||
[connection signal="pressed" from="Margin/Importer/Options/VisibleLayers/VisibleLayersCheckButton" to="." method="_save_config"]
|
||||
[connection signal="pressed" from="Margin/Importer/Options/WipeOldAnimations/WipeOldAnimationsCheckButton" to="." method="_save_config"]
|
||||
[connection signal="pressed" from="Margin/Importer/Import" to="." method="_on_import_pressed"]
|
||||
[connection signal="pressed" from="Margin/Importer/Reset" to="." method="_on_reset_pressed"]
|
|
@ -0,0 +1,55 @@
|
|||
@tool
|
||||
extends "res://addons/popochiu/editor/importers/aseprite/docks/aseprite_importer_inspector_dock.gd"
|
||||
|
||||
var _animation_player_path: String
|
||||
var _animation_creator = preload(
|
||||
"res://addons/popochiu/editor/importers/aseprite/animation_creator.gd"
|
||||
).new()
|
||||
|
||||
#region Godot ######################################################################################
|
||||
func _ready():
|
||||
if not target_node.has_node("AnimationPlayer"):
|
||||
PopochiuUtils.print_error(
|
||||
RESULT_CODE.get_error_message(RESULT_CODE.ERR_NO_ANIMATION_PLAYER_FOUND)
|
||||
)
|
||||
return
|
||||
|
||||
_animation_player_path = target_node.get_node("AnimationPlayer").get_path()
|
||||
|
||||
# Instantiate animation creator
|
||||
_animation_creator.init(_aseprite, file_system)
|
||||
|
||||
super()
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private ####################################################################################
|
||||
func _on_import_pressed():
|
||||
# Set everything up
|
||||
# This will populate _root_node and _options class variables
|
||||
super()
|
||||
|
||||
if _animation_player_path == "" or not _root_node.has_node(_animation_player_path):
|
||||
_show_message("AnimationPlayer not found")
|
||||
_importing = false
|
||||
return
|
||||
|
||||
var result = await _animation_creator.create_character_animations(
|
||||
target_node, _root_node.get_node(_animation_player_path), _options
|
||||
)
|
||||
_importing = false
|
||||
|
||||
if typeof(result) == TYPE_INT and result != RESULT_CODE.SUCCESS:
|
||||
PopochiuUtils.print_error(RESULT_CODE.get_error_message(result))
|
||||
_show_message("Some errors occurred. Please check output panel.", "Warning!")
|
||||
else:
|
||||
_show_message("%d animation tags processed." % [_tags_cache.size()], "Done!")
|
||||
|
||||
|
||||
func _customize_tag_ui(tag_row: AnimationTagRow):
|
||||
# Nothing special has to be done for Character tags
|
||||
pass
|
||||
|
||||
|
||||
#endregion
|
|
@ -0,0 +1 @@
|
|||
uid://cgc5psgxjoc17
|
|
@ -0,0 +1,117 @@
|
|||
@tool
|
||||
extends "res://addons/popochiu/editor/importers/aseprite/docks/aseprite_importer_inspector_dock.gd"
|
||||
|
||||
var _animation_creator = preload(\
|
||||
"res://addons/popochiu/editor/importers/aseprite/animation_creator.gd").new()
|
||||
|
||||
|
||||
#region Godot ######################################################################################
|
||||
func _ready():
|
||||
# Instantiate animation creator
|
||||
_animation_creator.init(_aseprite, file_system)
|
||||
|
||||
super()
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private ####################################################################################
|
||||
func _on_import_pressed():
|
||||
# Set everything up
|
||||
# This will populate _root_node and _options class variables
|
||||
super()
|
||||
|
||||
var props_container = _root_node.get_node("Props")
|
||||
var result: int = RESULT_CODE.SUCCESS
|
||||
|
||||
# Create a prop for each tag that must be imported
|
||||
# and populate it with the right sprite
|
||||
for tag in _options.get("tags"):
|
||||
# Ignore unwanted tags
|
||||
if not tag.import: continue
|
||||
|
||||
# Always convert to PascalCase as a standard
|
||||
# TODO: check Godot 4 standards, I can't find info
|
||||
var prop_name: String = tag.tag_name.to_pascal_case()
|
||||
|
||||
# In case the prop is there, use the one we already have
|
||||
var prop = props_container.get_node_or_null(prop_name)
|
||||
if prop == null:
|
||||
# Create a new prop if necessary, specifying the
|
||||
# interaction flags.
|
||||
prop = _create_prop(prop_name, tag.prop_clickable, tag.prop_visible)
|
||||
else:
|
||||
# Force flags (a bit redundant but they may have been changed
|
||||
# in the Importer interface, for already imported props)
|
||||
prop.clickable = tag.prop_clickable
|
||||
prop.visible = tag.prop_visible
|
||||
|
||||
prop.set_meta("ANIM_NAME", tag.tag_name)
|
||||
|
||||
for prop in props_container.get_children():
|
||||
if not prop.has_meta("ANIM_NAME"): continue
|
||||
# TODO: check if animation player exists in prop, if not add it
|
||||
# same for Sprite2D even if it should be there...
|
||||
|
||||
# Make the output folder match the prop's folder
|
||||
_options.output_folder = prop.scene_file_path.get_base_dir()
|
||||
|
||||
# Import a single tag animation
|
||||
result = await _animation_creator.create_prop_animations(
|
||||
prop,
|
||||
prop.get_meta("ANIM_NAME"),
|
||||
_options
|
||||
)
|
||||
|
||||
for prop in props_container.get_children():
|
||||
if not prop.has_meta("ANIM_NAME"): continue
|
||||
# Save the prop
|
||||
result = await _save_prop(prop)
|
||||
|
||||
# TODO: maybe check if this is better done with signals
|
||||
_importing = false
|
||||
|
||||
if typeof(result) == TYPE_INT and result != RESULT_CODE.SUCCESS:
|
||||
PopochiuUtils.print_error(RESULT_CODE.get_error_message(result))
|
||||
_show_message("Some errors occurred. Please check output panel.", "Warning!")
|
||||
else:
|
||||
await get_tree().create_timer(0.1).timeout
|
||||
|
||||
# Once the popup is closed, call _clean_props()
|
||||
_show_message(
|
||||
"%d animation tags processed." % [_tags_cache.size()],
|
||||
"Done!"
|
||||
)
|
||||
|
||||
|
||||
func _customize_tag_ui(tag_row: AnimationTagRow):
|
||||
# Show props-related buttons if we are in a room
|
||||
tag_row.show_prop_buttons()
|
||||
|
||||
|
||||
func _create_prop(name: String, is_clickable: bool = true, is_visible: bool = true):
|
||||
var factory = PopochiuPropFactory.new()
|
||||
var param := PopochiuPropFactory.PopochiuPropFactoryParam.new()
|
||||
param.obj_name = name
|
||||
param.room = _root_node
|
||||
param.is_interactive = is_clickable
|
||||
param.is_visible = is_visible
|
||||
|
||||
if factory.create(param) != ResultCodes.SUCCESS:
|
||||
return
|
||||
|
||||
return factory.get_obj_scene()
|
||||
|
||||
func _save_prop(prop: PopochiuProp):
|
||||
var packed_scene: PackedScene = PackedScene.new()
|
||||
packed_scene.pack(prop)
|
||||
if ResourceSaver.save(packed_scene, prop.scene_file_path) != OK:
|
||||
PopochiuUtils.print_error(
|
||||
"Couldn't save animations for prop %s at %s" %
|
||||
[prop.name, prop.scene_file_path]
|
||||
)
|
||||
return ResultCodes.ERR_CANT_SAVE_OBJ_SCENE
|
||||
return ResultCodes.SUCCESS
|
||||
|
||||
|
||||
#endregion
|
|
@ -0,0 +1 @@
|
|||
uid://cv4mdldfurgpc
|
Loading…
Add table
Add a link
Reference in a new issue