feat: base
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 6s
Create tag and build when new code gets to main / Export (push) Successful in 2m5s

This commit is contained in:
2025-06-27 23:11:54 +02:00
parent 9a79715e47
commit 00037d0270
394 changed files with 11399 additions and 11 deletions

View File

@ -0,0 +1,76 @@
@tool
extends Node
signal new_version_detected(version: String)
signal versions_matched
signal failed
const API_RELEASES_URL := "https://api.github.com/repos/%s/%s/releases"
@export var plugin_directory : String
@export var plugin_github_url : String :
set(value):
plugin_github_url = value
_update_urls()
@export_group("Advanced")
@export var auto_start : bool = false
@export var default_version : String = "0.0.0"
@export var replace_tag_name : String = "v"
@export var _test_action : bool = false :
set(value):
if value and Engine.is_editor_hint():
compare_versions()
@onready var _api_client : APIClient = $APIClient
var _zipball_url : String
func get_plugin_version() -> String :
if not plugin_directory.is_empty():
for enabled_plugin in ProjectSettings.get_setting("editor_plugins/enabled"):
if enabled_plugin.contains(plugin_directory):
var config := ConfigFile.new()
var error = config.load(enabled_plugin)
if error != OK:
return default_version
return config.get_value("plugin", "version", default_version)
return default_version
func _update_urls() -> void:
if plugin_github_url.is_empty(): return
if _api_client == null: return
var regex := RegEx.create_from_string("https:\\/\\/github\\.com\\/([\\w-]+)\\/([\\w-]+)\\/*")
var regex_match := regex.search(plugin_github_url)
if regex_match == null: return
var username := regex_match.get_string(1)
var repository := regex_match.get_string(2)
_api_client.api_url = API_RELEASES_URL % [username, repository]
func _on_api_client_request_failed(error) -> void:
failed.emit()
queue_free()
func _on_api_client_response_received(response_body) -> void:
if response_body is not Array:
failed.emit()
queue_free()
return
var latest_release : Dictionary = response_body.front()
var tag_name := default_version
if latest_release.has("tag_name"):
tag_name = latest_release["tag_name"]
if replace_tag_name:
tag_name = tag_name.replacen(replace_tag_name, "")
var current_tag_name = get_plugin_version()
if tag_name != current_tag_name:
new_version_detected.emit(tag_name)
else:
versions_matched.emit()
queue_free()
func compare_versions() -> void:
_api_client.request()
func _ready() -> void:
if auto_start:
compare_versions()

View File

@ -0,0 +1 @@
uid://ye1geusqp1gd

View File

@ -0,0 +1,16 @@
[gd_scene load_steps=3 format=3 uid="uid://b5m61gpvjy1ao"]
[ext_resource type="Script" uid="uid://ye1geusqp1gd" path="res://addons/maaacks_menus_template/installer/check_plugin_version.gd" id="1_aqelj"]
[ext_resource type="PackedScene" uid="uid://drhhakm62vjsy" path="res://addons/maaacks_menus_template/base/scenes/utilities/api_client.tscn" id="2_5myc0"]
[node name="CheckPluginVersion" type="Node"]
script = ExtResource("1_aqelj")
plugin_directory = "maaacks_menus_template"
plugin_github_url = "https://github.com/Maaack/Godot-Menus-Template"
[node name="APIClient" parent="." instance=ExtResource("2_5myc0")]
api_url = "https://api.github.com/repos/Maaack/Godot-Menus-Template/releases"
request_method = 0
[connection signal="request_failed" from="APIClient" to="." method="_on_api_client_request_failed"]
[connection signal="response_received" from="APIClient" to="." method="_on_api_client_response_received"]

View File

@ -0,0 +1,14 @@
[gd_scene format=3 uid="uid://cyx4i4v30bw4o"]
[node name="CopyConfirmationDialog" type="ConfirmationDialog"]
title = "Copy Examples"
initial_position = 2
size = Vector2i(1024, 148)
visible = true
exclusive = false
ok_button_text = "Yes"
dialog_text = "Plugin enabled. It is recommended to copy the example scenes to a destination outside of the addons/ folder before editing them.
Would you like to copy the examples now?"
dialog_autowrap = true
cancel_button_text = "No"

View File

@ -0,0 +1,15 @@
[gd_scene format=3 uid="uid://vgdxevcnv0vx"]
[node name="DeleteExamplesConfirmationDialog" type="ConfirmationDialog"]
title = "Delete Source Examples"
initial_position = 2
size = Vector2i(1024, 256)
visible = true
ok_button_text = "Yes"
dialog_text = "If the copied scenes work as expected, you may delete the source examples folder. This avoids confusing both developers and the Godot editor.
This will also remove the option to copy the examples again. However, one copy is enough for most use cases.
Would you like to delete the source examples folder now?"
dialog_autowrap = true
cancel_button_text = "No"

View File

@ -0,0 +1,11 @@
[gd_scene format=3 uid="uid://d03csqgcaxm0m"]
[node name="DeleteExamplesShortConfirmationDialog" type="ConfirmationDialog"]
title = "Delete Source Examples"
initial_position = 2
size = Vector2i(1024, 128)
visible = true
ok_button_text = "Yes"
dialog_text = "Are you sure you would like to delete the source examples folder?"
dialog_autowrap = true
cancel_button_text = "No"

View File

@ -0,0 +1,11 @@
[gd_scene format=3 uid="uid://ckx50am7thhd2"]
[node name="DestinationDialog" type="FileDialog"]
title = "Select a Destination"
initial_position = 2
size = Vector2i(1024, 640)
visible = true
exclusive = false
ok_button_text = "Select Current Folder"
mode_overrides_title = false
file_mode = 2

View File

@ -0,0 +1,12 @@
@tool
extends ConfirmationDialog
const SHORT_DESCRIPTION : String = "Choose a style for icons in the input remapping menu. This style can be changed later."
signal configuration_selected(index : int)
func _on_item_list_item_selected(index) -> void:
configuration_selected.emit(index)
func set_short_description() -> void:
%Label.text = SHORT_DESCRIPTION

View File

@ -0,0 +1 @@
uid://bduy6qihnm0qo

View File

@ -0,0 +1,83 @@
[gd_scene load_steps=14 format=3 uid="uid://d3x8m40qtdrj"]
[ext_resource type="Script" uid="uid://bduy6qihnm0qo" path="res://addons/maaacks_menus_template/installer/kenney_input_prompts_dialog.gd" id="1_nf1bc"]
[ext_resource type="Texture2D" uid="uid://cmni5hv40bfaa" path="res://addons/maaacks_menus_template/assets/input-icons/icons-filled-colored.png" id="2_0nqam"]
[ext_resource type="Texture2D" uid="uid://deskx061vlcgx" path="res://addons/maaacks_menus_template/assets/input-icons/icons-filled-white.png" id="3_ynuxh"]
[ext_resource type="Texture2D" uid="uid://bohem6w6kcl3x" path="res://addons/maaacks_menus_template/assets/input-icons/icons-outlined-colored.png" id="4_dqbfh"]
[ext_resource type="Texture2D" uid="uid://bq211jkfnm7k7" path="res://addons/maaacks_menus_template/assets/input-icons/icons-outlined-white.png" id="5_1tkva"]
[ext_resource type="Texture2D" uid="uid://bt1yqttw3d5xn" path="res://addons/maaacks_menus_template/assets/input-icons/icons-filled-colored-2x.png" id="6_r3yyh"]
[ext_resource type="Texture2D" uid="uid://bit8o3p506th6" path="res://addons/maaacks_menus_template/assets/input-icons/icons-filled-white-2x.png" id="7_xgp8o"]
[ext_resource type="Texture2D" uid="uid://cqb86gp1gh3y8" path="res://addons/maaacks_menus_template/assets/input-icons/icons-outlined-colored-2x.png" id="8_ag5dy"]
[ext_resource type="Texture2D" uid="uid://d3bsc6o2ae88q" path="res://addons/maaacks_menus_template/assets/input-icons/icons-outlined-white-2x.png" id="9_3b8mx"]
[ext_resource type="Texture2D" uid="uid://ix1d2e62f233" path="res://addons/maaacks_menus_template/assets/input-icons/icons-filled-colored-vector.svg" id="10_ag5dy"]
[ext_resource type="Texture2D" uid="uid://c37gofthe2bh3" path="res://addons/maaacks_menus_template/assets/input-icons/icons-filled-white-vector.svg" id="11_3b8mx"]
[ext_resource type="Texture2D" uid="uid://bsgf78aysgdnd" path="res://addons/maaacks_menus_template/assets/input-icons/icons-outlined-colored-vector.svg" id="12_rrkvx"]
[ext_resource type="Texture2D" uid="uid://c1lpc33fpmd4p" path="res://addons/maaacks_menus_template/assets/input-icons/icons-outlined-white-vector.svg" id="13_bkfjd"]
[node name="KenneyInputPromptsDialog" type="ConfirmationDialog"]
title = "Add Kenney Input Prompts Pack"
initial_position = 2
size = Vector2i(1024, 640)
visible = true
ok_button_text = "Yes"
dialog_autowrap = true
cancel_button_text = "No"
script = ExtResource("1_nf1bc")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
custom_minimum_size = Vector2(560, 443)
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 8.0
offset_top = 8.0
offset_right = -8.0
offset_bottom = -49.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 16
[node name="Label" type="Label" parent="VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(384, 0)
layout_mode = 2
text = "Would you like to install Kenney's Input Prompts?
This adds icons for a majority of input keys and devices in the input remapping menu. They are Creative Commons Zero (CC0) licensed, about 3.9 MB in size (7.6 MB with *.import files), and get installed into the assets folder.
Choose a style for icons in the input remapping menu. The style can be changed later."
autowrap_mode = 3
[node name="ItemList" type="ItemList" parent="VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
item_count = 12
same_column_width = true
item_0/text = "Filled and Colored Vector"
item_0/icon = ExtResource("10_ag5dy")
item_1/text = "Filled and White Vector"
item_1/icon = ExtResource("11_3b8mx")
item_2/text = "Outlined and Colored Vector"
item_2/icon = ExtResource("12_rrkvx")
item_3/text = "Outlined and White Vector"
item_3/icon = ExtResource("13_bkfjd")
item_4/text = "Filled and Colored 64x64"
item_4/icon = ExtResource("2_0nqam")
item_5/text = "Filled and White 64x64"
item_5/icon = ExtResource("3_ynuxh")
item_6/text = "Outlined and Colored 64x64"
item_6/icon = ExtResource("4_dqbfh")
item_7/text = "Outlined and White 64x64"
item_7/icon = ExtResource("5_1tkva")
item_8/text = "Filled and Colored 128x128"
item_8/icon = ExtResource("6_r3yyh")
item_9/text = "Filled and White 128x128"
item_9/icon = ExtResource("7_xgp8o")
item_10/text = "Outlined and Colored 128x128"
item_10/icon = ExtResource("8_ag5dy")
item_11/text = "Outlined and White 128x128"
item_11/icon = ExtResource("9_3b8mx")
[connection signal="item_selected" from="VBoxContainer/ItemList" to="." method="_on_item_list_item_selected"]

View File

@ -0,0 +1,343 @@
@tool
## Tool for installing icons and setting up the configuration of the input icon mapper.
extends Node
## Sent when the user selects to cancel the installation process.
signal canceled
## Sent when the installation process has completed.
signal completed
const RELATIVE_PATH_TO_CONFIGURE_SCENE = "scenes/menus/options_menu/input/input_options_menu.tscn"
const REIMPORT_CHECK_DELAY : float = 0.5
const OPEN_SCENE_DELAY : float = 0.5
const REGEX_PREFIX = """\\[node name="InputIconMapper" parent="." index="0"\\][\\s\\S]*"""
const FILLED_WHITE_CONFIGURATION = """
[node name="InputIconMapper" parent="." index="0"]
replace_strings = {
"Capslock": "Caps Lock",
"Generic Stick": "Generic Left Stick",
"Guide": "Home",
"Slash Back": "Back Slash",
"Slash Forward": "Slash",
"Stick L": "Left Stick",
"Stick R": "Right Stick",
"Trigger L 1": "Left Shoulder",
"Trigger L 2": "Left Trigger",
"Trigger R 1": "Right Shoulder",
"Trigger R 2": "Right Trigger"
}
filtered_strings = Array[String](["keyboard", "color", "button", "arrow"])
directories = Array[String](["res://assets/kenney_input-prompts/Keyboard & Mouse/Default", "res://assets/kenney_input-prompts/Generic/Default", "res://assets/kenney_input-prompts/Xbox Series/Default", "res://assets/kenney_input-prompts/PlayStation Series/Default", "res://assets/kenney_input-prompts/Nintendo Switch/Default", "res://assets/kenney_input-prompts/Steam Deck/Default"])
filter = "color"
ends_with = ".png"
not_ends_with = "outline.png"
"""
const FILLED_COLOR_CONFIGURATION = """
[node name="InputIconMapper" parent="." index="0"]
prioritized_strings = Array[String](["color"])
replace_strings = {
"Capslock": "Caps Lock",
"Generic Stick": "Generic Left Stick",
"Guide": "Home",
"Slash Back": "Back Slash",
"Slash Forward": "Slash",
"Stick L": "Left Stick",
"Stick R": "Right Stick",
"Trigger L 1": "Left Shoulder",
"Trigger L 2": "Left Trigger",
"Trigger R 1": "Right Shoulder",
"Trigger R 2": "Right Trigger"
}
filtered_strings = Array[String](["keyboard", "color", "button", "arrow"])
directories = Array[String](["res://assets/kenney_input-prompts/Keyboard & Mouse/Default", "res://assets/kenney_input-prompts/Generic/Default", "res://assets/kenney_input-prompts/Xbox Series/Default", "res://assets/kenney_input-prompts/PlayStation Series/Default", "res://assets/kenney_input-prompts/Nintendo Switch/Default", "res://assets/kenney_input-prompts/Steam Deck/Default"])
ends_with = ".png"
not_ends_with = "outline.png"
"""
const OUTLINED_WHITE_CONFIGURATION = """
[node name="InputIconMapper" parent="." index="0"]
prioritized_strings = Array[String](["outline"])
replace_strings = {
"Capslock": "Caps Lock",
"Generic Stick": "Generic Left Stick",
"Guide": "Home",
"Slash Back": "Back Slash",
"Slash Forward": "Slash",
"Stick L": "Left Stick",
"Stick R": "Right Stick",
"Trigger L 1": "Left Shoulder",
"Trigger L 2": "Left Trigger",
"Trigger R 1": "Right Shoulder",
"Trigger R 2": "Right Trigger"
}
filtered_strings = Array[String](["keyboard", "color", "button", "arrow", "outline"])
directories = Array[String](["res://assets/kenney_input-prompts/Keyboard & Mouse/Default", "res://assets/kenney_input-prompts/Generic/Default", "res://assets/kenney_input-prompts/Xbox Series/Default", "res://assets/kenney_input-prompts/PlayStation Series/Default", "res://assets/kenney_input-prompts/Nintendo Switch/Default", "res://assets/kenney_input-prompts/Steam Deck/Default"])
filter = "color"
ends_with = ".png"
"""
const OUTLINED_COLOR_CONFIGURATION = """
[node name="InputIconMapper" parent="." index="0"]
prioritized_strings = Array[String](["outline", "color"])
replace_strings = {
"Capslock": "Caps Lock",
"Generic Stick": "Generic Left Stick",
"Guide": "Home",
"Slash Back": "Back Slash",
"Slash Forward": "Slash",
"Stick L": "Left Stick",
"Stick R": "Right Stick",
"Trigger L 1": "Left Shoulder",
"Trigger L 2": "Left Trigger",
"Trigger R 1": "Right Shoulder",
"Trigger R 2": "Right Trigger"
}
filtered_strings = Array[String](["keyboard", "color", "button", "arrow", "outline"])
directories = Array[String](["res://assets/kenney_input-prompts/Keyboard & Mouse/Default", "res://assets/kenney_input-prompts/Generic/Default", "res://assets/kenney_input-prompts/Xbox Series/Default", "res://assets/kenney_input-prompts/PlayStation Series/Default", "res://assets/kenney_input-prompts/Nintendo Switch/Default", "res://assets/kenney_input-prompts/Steam Deck/Default"])
ends_with = ".png"
"""
const PACKAGE_EXTRA_DIRECTORIES := [
"Flairs",
"Nintendo Gamecube",
"Nintendo Switch 2",
"Nintendo Wii",
"Nintendo WiiU",
"Playdate",
"Steam Controller",
"Touch",
]
const PACKAGE_EXTRA_FILES := [
"Preview",
]
## Path start where the project examples have been copied.
@export_dir var copy_dir_path : String
## Path end where the zipped files are to be extracted.
@export var extract_extension : String
@onready var _download_and_extract_node : DownloadAndExtract = $DownloadAndExtract
@onready var _skip_installation_dialog : ConfirmationDialog = $SkipInstallationDialog
@onready var _kenney_input_prompts_dialog : ConfirmationDialog = $KenneyInputPromptsDialog
@onready var _installing_dialog : AcceptDialog = $InstallingDialog
@onready var _clean_up_dialog : ConfirmationDialog = $CleanUpDialog
@onready var _error_dialog : AcceptDialog = $ErrorDialog
@onready var _stage_label : Label = %StageLabel
@onready var _progress_bar : ProgressBar = %ProgressBar
var _configuration_index : int = -1
## State flag of whether the tool is waiting for the filesystem to finish scanning.
var scanning : bool = false
## State flag for whether the tool is waiting for the filesystem to finish reimporting.
var reimporting : bool = false
## Flag for whether the tool will force a download and extraction, even if the contents exist.
var force : bool = false
func _download_and_extract() -> void:
_installing_dialog.show()
_download_and_extract_node.run.call_deferred()
func _run_complete() -> void:
completed.emit()
queue_free()
func _clean_up_or_complete() -> void:
if _has_extras():
_clean_up_dialog.show()
else:
_run_complete()
func _process(_delta : float) -> void:
if _installing_dialog.visible:
_progress_bar.value = _download_and_extract_node.get_progress()
match _download_and_extract_node.stage:
DownloadAndExtract.Stage.DOWNLOAD:
_stage_label.text = "Downloading..."
DownloadAndExtract.Stage.SAVE:
_stage_label.text = "Saving..."
DownloadAndExtract.Stage.EXTRACT:
_stage_label.text = "Extracting..."
DownloadAndExtract.Stage.DELETE:
_stage_label.text = "Cleaning up..."
DownloadAndExtract.Stage.NONE:
_installing_dialog.hide()
elif scanning:
var file_system := EditorInterface.get_resource_filesystem()
if not file_system.is_scanning():
scanning = false
await get_tree().create_timer(REIMPORT_CHECK_DELAY).timeout
if reimporting:
await file_system.resources_reimported
reimporting = false
_configure_and_complete()
func _delete_recursive(path : String) -> void:
if not path.ends_with("/"):
path += "/"
var dir_access := DirAccess.open(path)
if dir_access == null:
return
var directories := dir_access.get_directories()
for directory in directories:
_delete_recursive(path + directory)
DirAccess.remove_absolute(path + directory)
var files := dir_access.get_files()
for file in files:
DirAccess.remove_absolute(path + file)
func get_full_path() -> String:
var full_path := copy_dir_path
if not full_path.ends_with("/"):
full_path += "/"
full_path += extract_extension
if not full_path.ends_with("/"):
full_path += "/"
return full_path
func _has_extras() -> bool:
var full_path := get_full_path()
var directories := DirAccess.get_directories_at(full_path)
for directory in directories:
for key in PACKAGE_EXTRA_DIRECTORIES:
if directory.contains(key):
return true
var files := DirAccess.get_files_at(full_path)
for file in files:
for key in PACKAGE_EXTRA_FILES:
if file.contains(key):
return true
return false
func _delete_extras() -> void:
var full_path := get_full_path()
var directories := DirAccess.get_directories_at(full_path)
for directory in directories:
for key in PACKAGE_EXTRA_DIRECTORIES:
if directory.contains(key):
_delete_recursive(full_path + directory)
DirAccess.remove_absolute(full_path + directory)
continue
var files := DirAccess.get_files_at(full_path)
for file in files:
for key in PACKAGE_EXTRA_FILES:
if file.contains(key):
DirAccess.remove_absolute(full_path + file)
continue
EditorInterface.get_resource_filesystem().scan()
func _configure_icons() -> void:
var input_options_menu_path := copy_dir_path + RELATIVE_PATH_TO_CONFIGURE_SCENE
var input_options_menu := FileAccess.get_file_as_string(input_options_menu_path)
var regex := RegEx.new()
regex.compile(REGEX_PREFIX + """\\[node""")
var result = regex.sub(input_options_menu, "[node")
if result == input_options_menu:
regex.clear()
regex.compile(REGEX_PREFIX)
result = regex.sub(input_options_menu, "")
input_options_menu = result
match(_configuration_index % 4):
0:
input_options_menu += FILLED_COLOR_CONFIGURATION
1:
input_options_menu += FILLED_WHITE_CONFIGURATION
2:
input_options_menu += OUTLINED_COLOR_CONFIGURATION
3:
input_options_menu += OUTLINED_WHITE_CONFIGURATION
match(_configuration_index / 4):
0:
input_options_menu = input_options_menu.replace("Default", "Vector").replace(".png", ".svg")
1:
pass
2:
input_options_menu = input_options_menu.replace("Default", "Double")
var file_rewrite := FileAccess.open(input_options_menu_path, FileAccess.WRITE)
file_rewrite.store_string(input_options_menu)
file_rewrite.close()
if input_options_menu_path in EditorInterface.get_open_scenes():
EditorInterface.reload_scene_from_path(input_options_menu_path)
else:
EditorInterface.open_scene_from_path(input_options_menu_path)
await get_tree().create_timer(OPEN_SCENE_DELAY).timeout
EditorInterface.save_scene()
await get_tree().create_timer(REIMPORT_CHECK_DELAY).timeout
_clean_up_or_complete()
func _configure_and_complete() -> void:
if _configuration_index >= 0:
_configure_icons()
return
_clean_up_or_complete()
func _scan_filesystem_and_reimport() -> void:
var file_system := EditorInterface.get_resource_filesystem()
file_system.scan()
scanning = true
await file_system.resources_reimporting
reimporting = true
func _enable_forced_install() -> void:
force = true
_download_and_extract_node.force = true
_kenney_input_prompts_dialog.show.call_deferred()
func _enable_skipped_install() -> void:
_kenney_input_prompts_dialog.set_short_description()
_kenney_input_prompts_dialog.show.call_deferred()
func _show_error_dialog(error : String) -> void:
_installing_dialog.hide()
_error_dialog.show()
_error_dialog.dialog_text = "%s!" % error
func _ready() -> void:
_skip_installation_dialog.hide()
_kenney_input_prompts_dialog.hide()
_installing_dialog.hide()
_installing_dialog.get_ok_button().hide()
_clean_up_dialog.hide()
_error_dialog.hide()
_download_and_extract_node.extract_path = get_full_path()
if _download_and_extract_node.extract_path_exists():
_skip_installation_dialog.show()
else:
_kenney_input_prompts_dialog.show()
func _on_kenney_input_prompts_dialog_canceled() -> void:
canceled.emit()
queue_free()
func _on_kenney_input_prompts_dialog_configuration_selected(index: int) -> void:
_configuration_index = index
func _on_kenney_input_prompts_dialog_confirmed() -> void:
if _download_and_extract_node.extract_path_exists() and not force:
_configure_and_complete()
return
_download_and_extract()
func _on_skip_installation_dialog_canceled() -> void:
_enable_forced_install()
func _on_skip_installation_dialog_confirmed() -> void:
_enable_skipped_install()
func _on_error_dialog_confirmed() -> void:
queue_free()
func _on_error_dialog_canceled() -> void:
queue_free()
func _on_download_and_extract_run_completed() -> void:
_scan_filesystem_and_reimport()
func _on_download_and_extract_run_failed(error : String) -> void:
_show_error_dialog(error)
func _on_clean_up_dialog_confirmed() -> void:
_delete_extras()
_run_complete()
func _on_clean_up_dialog_canceled() -> void:
_run_complete()

View File

@ -0,0 +1 @@
uid://ca36dy2vkk46q

View File

@ -0,0 +1,92 @@
[gd_scene load_steps=4 format=3 uid="uid://d27twrcwmfxrs"]
[ext_resource type="Script" uid="uid://ca36dy2vkk46q" path="res://addons/maaacks_menus_template/installer/kenney_input_prompts_installer.gd" id="1_ebstj"]
[ext_resource type="PackedScene" uid="uid://d3x8m40qtdrj" path="res://addons/maaacks_menus_template/installer/kenney_input_prompts_dialog.tscn" id="1_pslk0"]
[ext_resource type="PackedScene" uid="uid://dlkmofxhavh10" path="res://addons/maaacks_menus_template/base/scenes/utilities/download_and_extract.tscn" id="3_ebstj"]
[node name="KenneyInputPromptsInstaller" type="Node"]
script = ExtResource("1_ebstj")
copy_dir_path = "res://"
extract_extension = "assets/kenney_input-prompts"
[node name="DownloadAndExtract" parent="." instance=ExtResource("3_ebstj")]
zip_url = "https://github.com/Maaack/Kenney-Input-Prompts/archive/refs/tags/1.3.zip"
extract_path = "res://assets/kenney_input-prompts/"
skip_base_zip_dir = true
zip_file_path = "res://kenney_input-prompts.zip"
metadata/_custom_type_script = "uid://bqu3bc0tttrfk"
[node name="SkipInstallationDialog" type="ConfirmationDialog" parent="."]
title = "Skip Installation?"
initial_position = 2
size = Vector2i(682, 160)
ok_button_text = "Skip"
dialog_text = "The input prompts pack appears to already be installed.
Do you want to force a reinstall of the pack, or skip to picking a style?"
cancel_button_text = "Reinstall"
[node name="KenneyInputPromptsDialog" parent="." instance=ExtResource("1_pslk0")]
visible = false
[node name="InstallingDialog" type="AcceptDialog" parent="."]
title = "Installing..."
initial_position = 2
size = Vector2i(400, 100)
[node name="MarginContainer" type="MarginContainer" parent="InstallingDialog"]
offset_left = 4.0
offset_top = 4.0
offset_right = 396.0
offset_bottom = 96.0
theme_override_constants/margin_left = 16
theme_override_constants/margin_top = 16
theme_override_constants/margin_right = 16
theme_override_constants/margin_bottom = 16
[node name="VBoxContainer" type="VBoxContainer" parent="InstallingDialog/MarginContainer"]
layout_mode = 2
alignment = 1
[node name="StageLabel" type="Label" parent="InstallingDialog/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
horizontal_alignment = 1
vertical_alignment = 1
[node name="ProgressBar" type="ProgressBar" parent="InstallingDialog/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
max_value = 1.0
step = 0.001
[node name="CleanUpDialog" type="ConfirmationDialog" parent="."]
auto_translate_mode = 1
title = "Clean Up Extra Content?"
initial_position = 2
size = Vector2i(1024, 210)
ok_button_text = "Yes"
dialog_text = "Kenney's Input Prompts contains extra content not used by the input remapping menu.
This includes icons for devices not currently detected and preview images. Removing the extras cuts the total size of extracted assets by almost 50%. The option to change input icon styles will remain available after the clean up, too.
Would you like to have the extra content removed?"
dialog_autowrap = true
cancel_button_text = "No"
[node name="ErrorDialog" type="AcceptDialog" parent="."]
title = "Error!"
initial_position = 2
size = Vector2i(400, 128)
[connection signal="run_completed" from="DownloadAndExtract" to="." method="_on_download_and_extract_run_completed"]
[connection signal="run_failed" from="DownloadAndExtract" to="." method="_on_download_and_extract_run_failed"]
[connection signal="canceled" from="SkipInstallationDialog" to="." method="_on_skip_installation_dialog_canceled"]
[connection signal="confirmed" from="SkipInstallationDialog" to="." method="_on_skip_installation_dialog_confirmed"]
[connection signal="canceled" from="KenneyInputPromptsDialog" to="." method="_on_kenney_input_prompts_dialog_canceled"]
[connection signal="configuration_selected" from="KenneyInputPromptsDialog" to="." method="_on_kenney_input_prompts_dialog_configuration_selected"]
[connection signal="confirmed" from="KenneyInputPromptsDialog" to="." method="_on_kenney_input_prompts_dialog_confirmed"]
[connection signal="canceled" from="CleanUpDialog" to="." method="_on_clean_up_dialog_canceled"]
[connection signal="confirmed" from="CleanUpDialog" to="." method="_on_clean_up_dialog_confirmed"]
[connection signal="canceled" from="ErrorDialog" to="." method="_on_error_dialog_canceled"]
[connection signal="confirmed" from="ErrorDialog" to="." method="_on_error_dialog_confirmed"]

View File

@ -0,0 +1,14 @@
[gd_scene format=3 uid="uid://b8kr3y0cjxr8m"]
[node name="MainSceneConfirmationDialog" type="ConfirmationDialog"]
title = "Update Main Scene"
initial_position = 2
size = Vector2i(1024, 192)
visible = true
exclusive = false
ok_button_text = "Yes"
dialog_text = "Would you like to update the project's main scene?
"
dialog_autowrap = true
cancel_button_text = "No"

View File

@ -0,0 +1,36 @@
; Project settings override file.
; Adds gamepad inputs to built-in actions.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
[input]
ui_accept={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194309,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null)
]
}
ui_cancel={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":4,"pressure":0.0,"pressed":true,"script":null)
]
}
ui_page_up={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194323,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":true,"script":null)
]
}
ui_page_down={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194324,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":true,"script":null)
]
}

View File

@ -0,0 +1,13 @@
[gd_scene format=3 uid="uid://b8808yj7a0ghj"]
[node name="PlayOpeningConfirmationDialog" type="ConfirmationDialog"]
title = "Run & Test"
initial_position = 2
size = Vector2i(1024, 148)
visible = true
ok_button_text = "Yes"
dialog_text = "It is recommended to run the opening scene of the plugin and test if any issues occurred during the copying process.
Would you like to run and test the scenes now?"
dialog_autowrap = true
cancel_button_text = "No"

View File

@ -0,0 +1,33 @@
@tool
extends ConfirmationDialog
signal theme_selected(theme_file: String)
@export_dir var theme_directories : Array[String] :
set(value):
theme_directories = value
if is_inside_tree():
%FileLister.directories = theme_directories
_fill_with_themes()
func _fill_with_themes() -> void:
%ItemList.clear()
for file in %FileLister.files:
if file is String:
var readable_name = file.get_file().get_basename().capitalize()
%ItemList.add_item(readable_name)
func _ready() -> void:
get_ok_button().disabled = true
func _preview_theme(theme_file: String) -> void:
var theme_resource : Theme = load(theme_file)
if theme_resource == null: return
%ThemePreviewContainer.theme = theme_resource
func _on_item_list_item_selected(index) -> void:
get_ok_button().disabled = false
if index < %FileLister.files.size():
var file = %FileLister.files[index]
_preview_theme(file)
theme_selected.emit(file)

View File

@ -0,0 +1 @@
uid://c6p8xjvlrgsfk

View File

@ -0,0 +1,178 @@
[gd_scene load_steps=3 format=3 uid="uid://d25mdvmlbn35"]
[ext_resource type="Script" uid="uid://c6p8xjvlrgsfk" path="res://addons/maaacks_menus_template/installer/theme_selection_dialog.gd" id="1_5u0gx"]
[ext_resource type="Script" uid="uid://bij7wsh8d44gv" path="res://addons/maaacks_menus_template/base/scripts/file_lister.gd" id="2_luhgx"]
[node name="ThemeSelectionDialog" type="ConfirmationDialog"]
title = "Use a Starter Theme"
initial_position = 2
size = Vector2i(1024, 704)
visible = true
ok_button_text = "Yes"
dialog_autowrap = true
cancel_button_text = "No"
script = ExtResource("1_5u0gx")
[node name="FileLister" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("2_luhgx")
ends_with = ".tres"
[node name="VBoxContainer" type="VBoxContainer" parent="."]
custom_minimum_size = Vector2(560, 443)
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 8.0
offset_top = 8.0
offset_right = -8.0
offset_bottom = -49.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 16
[node name="Label" type="Label" parent="VBoxContainer"]
custom_minimum_size = Vector2(384, 0)
layout_mode = 2
text = "A custom theme was not detected for the project. Starter options are provided below. These can be customized as needed.
Requires restarting the editor to take full effect."
autowrap_mode = 3
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="ItemList" type="ItemList" parent="VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="VSeparator" type="VSeparator" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/margin_left = 16
theme_override_constants/margin_right = 16
[node name="ThemePreviewContainer" type="TabContainer" parent="VBoxContainer/HBoxContainer/MarginContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
current_tab = 0
[node name="Tab1" type="Control" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer"]
layout_mode = 2
metadata/_tab_index = 0
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Label"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="Button" type="Button" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Button"
[node name="Button2" type="Button" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
toggle_mode = true
button_pressed = true
text = "Button"
[node name="Button3" type="Button" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
disabled = true
text = "Button"
[node name="CheckButton" type="CheckButton" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "CheckButton"
[node name="CheckBox" type="CheckBox" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "CheckBox"
[node name="MenuButton" type="MenuButton" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "MenuButton"
[node name="OptionButton" type="OptionButton" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab1/MarginContainer/VBoxContainer"]
layout_mode = 2
selected = 0
item_count = 2
popup/item_0/text = "OptionButton"
popup/item_0/id = 0
popup/item_1/text = "OptionButton2"
popup/item_1/id = 1
[node name="Tab2" type="Control" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 1
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab2"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab2/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab2/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Another label"
horizontal_alignment = 1
[node name="LineEdit" type="LineEdit" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab2/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="TextEdit" type="TextEdit" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab2/MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="HSlider" type="HSlider" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab2/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="HScrollBar" type="HScrollBar" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab2/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab2/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="ProgressBar" type="ProgressBar" parent="VBoxContainer/HBoxContainer/MarginContainer/ThemePreviewContainer/Tab2/MarginContainer/VBoxContainer"]
layout_mode = 2
value = 50.0
[connection signal="item_selected" from="VBoxContainer/HBoxContainer/ItemList" to="." method="_on_item_list_item_selected"]

View File

@ -0,0 +1,153 @@
@tool
extends Node
signal update_completed
const API_RELEASES_URL := "https://api.github.com/repos/%s/%s/releases"
const UPDATE_CONFIRMATION_MESSAGE := "This will update the contents of the plugin folder (addons/%s/).\nFiles outside of the plugin folder will not be affected.\n\nUpdate %s to v%s?"
const PLUGIN_EXTRACT_PATH := "res://addons/%s/"
const PLUGIN_TEMP_ZIP_PATH := "res://%s_%s_update.zip"
@export var plugin_directory : String
@export var plugin_github_url : String :
set(value):
plugin_github_url = value
_update_urls()
@export_group("Advanced")
@export var auto_start : bool = false
@export var default_version : String = "0.0.0"
@export var replace_tag_name : String = "v"
@export var _test_action : bool = false :
set(value):
if value and Engine.is_editor_hint():
get_newest_version()
@onready var _api_client : APIClient = $APIClient
@onready var _download_and_extract_node : DownloadAndExtract = $DownloadAndExtract
@onready var _update_confirmation_dialog : ConfirmationDialog = $UpdateConfirmationDialog
@onready var _installing_dialog : AcceptDialog = $InstallingDialog
@onready var _error_dialog : AcceptDialog = $ErrorDialog
@onready var _success_dialog : AcceptDialog = $SuccessDialog
@onready var _release_label : RichTextLabel = %ReleaseLabel
@onready var _update_label : Label = %UpdateLabel
@onready var _release_notes_button : LinkButton = %ReleaseNotesButton
@onready var _release_notes_panel : Panel = %ReleaseNotesPanel
@onready var _stage_label : Label = %StageLabel
@onready var _progress_bar : ProgressBar = %ProgressBar
var _zipball_url : String
var _newest_version : String
var _plugin_name : String
var _current_plugin_version : String
func _load_plugin_details() -> void:
if plugin_directory.is_empty(): return
for enabled_plugin in ProjectSettings.get_setting("editor_plugins/enabled"):
if enabled_plugin.contains(plugin_directory):
var config := ConfigFile.new()
var error = config.load(enabled_plugin)
if error != OK:
return
_current_plugin_version = config.get_value("plugin", "version", default_version)
_plugin_name = config.get_value("plugin", "name", "Plugin")
func _update_urls() -> void:
if plugin_github_url.is_empty(): return
if _api_client == null: return
var regex := RegEx.create_from_string("https:\\/\\/github\\.com\\/([\\w-]+)\\/([\\w-]+)\\/*")
var regex_match := regex.search(plugin_github_url)
if regex_match == null: return
var username := regex_match.get_string(1)
var repository := regex_match.get_string(2)
_api_client.api_url = API_RELEASES_URL % [username, repository]
func _show_error_dialog(error : String) -> void:
_error_dialog.show()
_error_dialog.dialog_text = "%s!" % error
func _show_success_dialog() -> void:
_success_dialog.show()
_success_dialog.dialog_text = "%s updated to v%s." % [_plugin_name, _newest_version]
func _on_api_client_request_failed(error : String) -> void:
_show_error_dialog(error)
func _on_api_client_response_received(response_body : Variant) -> void:
if response_body is not Array:
push_error("Response was not an array")
return
var latest_release : Dictionary = response_body.front()
_newest_version = default_version
if latest_release.has("tag_name"):
var tag_name = latest_release["tag_name"]
if replace_tag_name:
tag_name = tag_name.replacen(replace_tag_name, "")
_newest_version = tag_name
if latest_release.has("zipball_url"):
_zipball_url = latest_release["zipball_url"]
_download_and_extract_node.zip_url = _zipball_url
_download_and_extract_node.zip_file_path = PLUGIN_TEMP_ZIP_PATH % [plugin_directory, _newest_version]
_update_label.text = UPDATE_CONFIRMATION_MESSAGE % [plugin_directory, _plugin_name, _newest_version]
if latest_release.has("body"):
_release_label.text = latest_release["body"]
_update_confirmation_dialog.show()
func _on_download_and_extract_zip_saved() -> void:
OS.move_to_trash(ProjectSettings.globalize_path(PLUGIN_EXTRACT_PATH % plugin_directory))
func _on_download_and_extract_run_failed(error : String) -> void:
_show_error_dialog(error)
func _on_download_and_extract_run_completed() -> void:
update_completed.emit()
_show_success_dialog()
func _on_error_dialog_canceled() -> void:
queue_free()
func _on_error_dialog_confirmed() -> void:
queue_free()
func _on_success_dialog_canceled() -> void:
queue_free()
func _on_success_dialog_confirmed() -> void:
queue_free()
func _on_update_confirmation_dialog_canceled() -> void:
queue_free()
func _on_update_confirmation_dialog_confirmed() -> void:
_download_and_extract_node.run()
_installing_dialog.show()
func _on_release_notes_button_pressed() -> void:
_release_notes_panel.show()
_release_notes_button.hide()
func get_newest_version() -> void:
_api_client.request()
func _ready() -> void:
_load_plugin_details()
_update_confirmation_dialog.hide()
_installing_dialog.hide()
_error_dialog.hide()
_success_dialog.hide()
if auto_start:
get_newest_version()
func _process(_delta : float) -> void:
if _installing_dialog.visible:
_progress_bar.value = _download_and_extract_node.get_progress()
match _download_and_extract_node.stage:
DownloadAndExtract.Stage.DOWNLOAD:
_stage_label.text = "Downloading..."
DownloadAndExtract.Stage.SAVE:
_stage_label.text = "Saving..."
DownloadAndExtract.Stage.EXTRACT:
_stage_label.text = "Extracting..."
DownloadAndExtract.Stage.DELETE:
_stage_label.text = "Cleaning up..."
DownloadAndExtract.Stage.NONE:
_installing_dialog.hide()

View File

@ -0,0 +1 @@
uid://cwj8dpqveao6o

View File

@ -0,0 +1,128 @@
[gd_scene load_steps=4 format=3 uid="uid://gynblau0ojia"]
[ext_resource type="Script" uid="uid://cwj8dpqveao6o" path="res://addons/maaacks_menus_template/installer/update_plugin.gd" id="1_s6qpc"]
[ext_resource type="PackedScene" uid="uid://drhhakm62vjsy" path="res://addons/maaacks_menus_template/base/scenes/utilities/api_client.tscn" id="2_s6pdq"]
[ext_resource type="PackedScene" uid="uid://dlkmofxhavh10" path="res://addons/maaacks_menus_template/base/scenes/utilities/download_and_extract.tscn" id="3_s6pdq"]
[node name="UpdatePlugin" type="Node"]
script = ExtResource("1_s6qpc")
plugin_directory = "maaacks_menus_template"
plugin_github_url = "https://github.com/Maaack/Godot-Menus-Template"
[node name="APIClient" parent="." instance=ExtResource("2_s6pdq")]
api_url = "https://api.github.com/repos/Maaack/Godot-Menus-Template/releases"
request_method = 0
[node name="DownloadAndExtract" parent="." instance=ExtResource("3_s6pdq")]
extract_path = "res://"
path_match_string = "addons/"
skip_base_zip_dir = true
force = true
[node name="UpdateConfirmationDialog" type="ConfirmationDialog" parent="."]
auto_translate_mode = 1
title = "Update Plugin?"
initial_position = 2
size = Vector2i(640, 360)
dialog_autowrap = true
[node name="MarginContainer" type="MarginContainer" parent="UpdateConfirmationDialog"]
offset_left = 8.0
offset_top = 8.0
offset_right = 632.0
offset_bottom = 311.0
theme_override_constants/margin_bottom = 16
[node name="VBoxContainer" type="VBoxContainer" parent="UpdateConfirmationDialog/MarginContainer"]
layout_mode = 2
[node name="UpdateLabel" type="Label" parent="UpdateConfirmationDialog/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "This will update the contents of the plugin folder (addons/plugin_directory/).
Files outside of the plugin folder will not be affected.
Update to v0.0.0?"
[node name="HSeparator" type="HSeparator" parent="UpdateConfirmationDialog/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="ReleaseNotesButton" type="LinkButton" parent="UpdateConfirmationDialog/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Show Release Notes"
[node name="ReleaseNotesPanel" type="Panel" parent="UpdateConfirmationDialog/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(0, 420)
layout_mode = 2
size_flags_vertical = 3
[node name="ReleaseLabel" type="RichTextLabel" parent="UpdateConfirmationDialog/MarginContainer/VBoxContainer/ReleaseNotesPanel"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_vertical = 3
[node name="InstallingDialog" type="AcceptDialog" parent="."]
auto_translate_mode = 1
title = "Installing..."
initial_position = 2
size = Vector2i(400, 111)
[node name="MarginContainer" type="MarginContainer" parent="InstallingDialog"]
offset_left = 4.0
offset_top = 4.0
offset_right = 396.0
offset_bottom = 96.0
theme_override_constants/margin_left = 16
theme_override_constants/margin_top = 16
theme_override_constants/margin_right = 16
theme_override_constants/margin_bottom = 16
[node name="VBoxContainer" type="VBoxContainer" parent="InstallingDialog/MarginContainer"]
layout_mode = 2
alignment = 1
[node name="StageLabel" type="Label" parent="InstallingDialog/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
horizontal_alignment = 1
vertical_alignment = 1
[node name="ProgressBar" type="ProgressBar" parent="InstallingDialog/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
max_value = 1.0
step = 0.001
[node name="ErrorDialog" type="AcceptDialog" parent="."]
auto_translate_mode = 1
title = "Error!"
initial_position = 2
size = Vector2i(400, 128)
[node name="SuccessDialog" type="AcceptDialog" parent="."]
auto_translate_mode = 1
title = "Update Complete"
initial_position = 2
size = Vector2i(400, 128)
dialog_text = "%s updated to v%s."
[connection signal="request_failed" from="APIClient" to="." method="_on_api_client_request_failed"]
[connection signal="response_received" from="APIClient" to="." method="_on_api_client_response_received"]
[connection signal="run_completed" from="DownloadAndExtract" to="." method="_on_download_and_extract_run_completed"]
[connection signal="run_failed" from="DownloadAndExtract" to="." method="_on_download_and_extract_run_failed"]
[connection signal="zip_saved" from="DownloadAndExtract" to="." method="_on_download_and_extract_zip_saved"]
[connection signal="canceled" from="UpdateConfirmationDialog" to="." method="_on_update_confirmation_dialog_canceled"]
[connection signal="confirmed" from="UpdateConfirmationDialog" to="." method="_on_update_confirmation_dialog_confirmed"]
[connection signal="pressed" from="UpdateConfirmationDialog/MarginContainer/VBoxContainer/ReleaseNotesButton" to="." method="_on_release_notes_button_pressed"]
[connection signal="canceled" from="ErrorDialog" to="." method="_on_error_dialog_canceled"]
[connection signal="confirmed" from="ErrorDialog" to="." method="_on_error_dialog_confirmed"]
[connection signal="canceled" from="SuccessDialog" to="." method="_on_success_dialog_canceled"]
[connection signal="confirmed" from="SuccessDialog" to="." method="_on_success_dialog_confirmed"]