This commit is contained in:
Melody Becker 2024-11-28 18:31:55 +01:00
commit 2747ffa9b0
40 changed files with 2240 additions and 0 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
# Godot 4+ specific ignores
.godot/
/android/

3
.plugged/index.cfg Normal file
View file

@ -0,0 +1,3 @@
[plugin]
installed={}

View file

@ -0,0 +1,27 @@
static func expected_version(current, later_or_equal, before=""):
var is_expected = false
is_expected = compare_version_string(current, later_or_equal) >= 0
if not is_expected:
return is_expected
if before.length() > 0:
is_expected = compare_version_string(current, before) < 0
return is_expected
static func compare_version_string(v1, v2):
var v1_arr = v1.split(".")
var v2_arr = v2.split(".")
assert(v1_arr.size() == 3)
assert(v2_arr.size() == 3)
var value = 0
for i in 3:
var n1 = int(v1_arr[i])
var n2 = int(v2_arr[i])
value = compare_number(n1, n2)
if value != 0:
break
return value
static func compare_number(v1, v2):
return 0 if v1 == v2 else (1 if v1 > v2 else -1)

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://djvngsd55wxhs"
path="res://.godot/imported/add.png-621a4be1b942ed06c9140cb74c31abe2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/add.png"
dest_files=["res://.godot/imported/add.png-621a4be1b942ed06c9140cb74c31abe2.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://vv157kc8qi2c"
path="res://.godot/imported/edit_internal.png-061b166639fc3fd2f8ef9610c485c3fa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/edit_internal.png"
dest_files=["res://.godot/imported/edit_internal.png-061b166639fc3fd2f8ef9610c485c3fa.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bcqbcs5lk7njk"
path="res://.godot/imported/import_check.png-2f45ffda2b43464b03cd006cdaf7e772.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/import_check.png"
dest_files=["res://.godot/imported/import_check.png-2f45ffda2b43464b03cd006cdaf7e772.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://lffm4bx4h2y2"
path="res://.godot/imported/import_fail.png-051695dac0afab3cc15844d66713cd8d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/import_fail.png"
dest_files=["res://.godot/imported/import_fail.png-051695dac0afab3cc15844d66713cd8d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cgts01urkfo46"
path="res://.godot/imported/progress1.png-b701146896a0cd13b3b1213eca4aefaf.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/progress/progress1.png"
dest_files=["res://.godot/imported/progress1.png-b701146896a0cd13b3b1213eca4aefaf.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cj7jy1jh5cutb"
path="res://.godot/imported/progress2.png-b7faf28624cb0f60e429a592a58c6ee4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/progress/progress2.png"
dest_files=["res://.godot/imported/progress2.png-b7faf28624cb0f60e429a592a58c6ee4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dymxcsmwminoi"
path="res://.godot/imported/progress3.png-f5d97e18b2237ef205acfdce7d4133d6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/progress/progress3.png"
dest_files=["res://.godot/imported/progress3.png-f5d97e18b2237ef205acfdce7d4133d6.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://wosx7pjrwtiw"
path="res://.godot/imported/progress4.png-ea4cf0010c5c85d77c4678da413c2ae8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/progress/progress4.png"
dest_files=["res://.godot/imported/progress4.png-ea4cf0010c5c85d77c4678da413c2ae8.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://kqh2l4lmud66"
path="res://.godot/imported/progress5.png-1a5a4b8c789b45a8292beed39d7d3a40.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/progress/progress5.png"
dest_files=["res://.godot/imported/progress5.png-1a5a4b8c789b45a8292beed39d7d3a40.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cgpnu44qyu6k3"
path="res://.godot/imported/progress6.png-291be2c54ac04191c46b210bc746b5d8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/progress/progress6.png"
dest_files=["res://.godot/imported/progress6.png-291be2c54ac04191c46b210bc746b5d8.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://sred54ktpynr"
path="res://.godot/imported/progress7.png-b7f8b3304beb293d02138afa69666fa3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/progress/progress7.png"
dest_files=["res://.godot/imported/progress7.png-b7f8b3304beb293d02138afa69666fa3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dvgd0gmpoo216"
path="res://.godot/imported/progress8.png-e052617913242937886f27a9f5422ac5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/progress/progress8.png"
dest_files=["res://.godot/imported/progress8.png-e052617913242937886f27a9f5422ac5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,29 @@
[gd_resource type="AnimatedTexture" load_steps=9 format=2]
[ext_resource path="res://addons/gd-plug-ui/assets/icons/progress/progress1.png" type="Texture" id=1]
[ext_resource path="res://addons/gd-plug-ui/assets/icons/progress/progress6.png" type="Texture" id=2]
[ext_resource path="res://addons/gd-plug-ui/assets/icons/progress/progress7.png" type="Texture" id=3]
[ext_resource path="res://addons/gd-plug-ui/assets/icons/progress/progress5.png" type="Texture" id=4]
[ext_resource path="res://addons/gd-plug-ui/assets/icons/progress/progress2.png" type="Texture" id=5]
[ext_resource path="res://addons/gd-plug-ui/assets/icons/progress/progress4.png" type="Texture" id=6]
[ext_resource path="res://addons/gd-plug-ui/assets/icons/progress/progress3.png" type="Texture" id=7]
[ext_resource path="res://addons/gd-plug-ui/assets/icons/progress/progress8.png" type="Texture" id=8]
[resource]
flags = 4
frames = 8
frame_0/texture = ExtResource( 1 )
frame_1/texture = ExtResource( 5 )
frame_1/delay_sec = 0.0
frame_2/texture = ExtResource( 7 )
frame_2/delay_sec = 0.0
frame_3/texture = ExtResource( 6 )
frame_3/delay_sec = 0.0
frame_4/texture = ExtResource( 4 )
frame_4/delay_sec = 0.0
frame_5/texture = ExtResource( 2 )
frame_5/delay_sec = 0.0
frame_6/texture = ExtResource( 3 )
frame_6/delay_sec = 0.0
frame_7/texture = ExtResource( 8 )
frame_7/delay_sec = 0.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cole0s5mc4l31"
path="res://.godot/imported/refresh.png-751efcf923f713368de638e48ebe9d26.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/gd-plug-ui/assets/icons/refresh.png"
dest_files=["res://.godot/imported/refresh.png-751efcf923f713368de638e48ebe9d26.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -0,0 +1,7 @@
[plugin]
name="gd-plug-ui"
description=""
author="imjp94"
version="0.2.1"
script="plugin.gd"

View file

@ -0,0 +1,80 @@
@tool
extends EditorPlugin
const Utils = preload("Utils.gd")
const PluginSettings = preload("scene/plugin_settings/PluginSettings.tscn")
var plugin_config = ConfigFile.new()
var plugin_settings = PluginSettings.instantiate()
var plugins_tab
var plugins_tab_update_btn
func _enter_tree():
add_control_to_container(EditorPlugin.CONTAINER_PROJECT_SETTING_TAB_LEFT, plugin_settings)
plugin_settings.connect("updated", _on_plugin_settings_updated)
plugin_settings.connect("gd_plug_loaded", _on_plugin_settings_gd_plug_loaded)
var tab_container = plugin_settings.get_parent()
for child in tab_container.get_children():
if child.name == "Plugins":
plugins_tab = child
break
if plugins_tab:
tab_container.move_child(plugin_settings, plugins_tab.get_index())
else:
tab_container.move_child(plugin_settings, tab_container.get_child_count()-1)
for child in plugins_tab.get_children():
if child is HBoxContainer:
for grandchild in child.get_children():
if grandchild is Button:
if grandchild.text == "Update":
plugins_tab_update_btn = grandchild
plugins_tab_update_btn.connect("pressed", self, "_on_plugins_tab_update_btn_pressed")
break
plugin_settings.load_gd_plug()
func _on_plugin_settings_gd_plug_loaded(gd_plug):
check_compatibility(gd_plug.VERSION)
func _on_plugin_settings_updated():
if plugins_tab_update_btn:
plugins_tab_update_btn.emit_signal("pressed") # Programmatically press update button in "Plugins" tab
func _exit_tree():
if is_instance_valid(plugin_settings):
remove_control_from_container(EditorPlugin.CONTAINER_PROJECT_SETTING_TAB_LEFT, plugin_settings)
plugin_settings.queue_free()
func check_compatibility(gd_plug_version):
plugin_config.load("res://addons/gd-plug-ui/plugin.cfg")
var gd_plug_ui_version = plugin_config.get_value("plugin", "version", "0.0.0")
var later_or_equal = ""
var before = ""
match gd_plug_ui_version:
"0.2.0":
later_or_equal = "0.2.5"
"0.1.0":
later_or_equal = "0.1.4"
before = "0.2.0"
"0.0.0":
print("Failed to read gd-plug-ui version string")
_:
later_or_equal = "0.1.3"
var is_version_expected = Utils.expected_version(gd_plug_version, later_or_equal, before)
if not is_version_expected:
var dialog = AcceptDialog.new()
var text = "gd-plug-ui(%s) is not compatible with " % gd_plug_ui_version
text += "current gd-plug(%s), " % gd_plug_version
text += "expected >=%s" % later_or_equal if before.length() == 0 else " expected >=%s or %s<" % [later_or_equal, before]
dialog.dialog_text = text
plugin_settings.add_child(dialog)
# add_control_to_container(EditorPlugin.CONTAINER_PROJECT_SETTING_TAB_LEFT, dialog)
dialog.popup_centered()
await dialog.confirmed
dialog.queue_free()
if is_instance_valid(plugin_settings):
remove_control_from_container(EditorPlugin.CONTAINER_PROJECT_SETTING_TAB_LEFT, plugin_settings)
plugin_settings.queue_free()

View file

@ -0,0 +1,306 @@
@tool
extends Control
signal gd_plug_loaded(gd_plug)
signal updated()
enum PLUGIN_STATUS {
PLUGGED, UNPLUGGED, INSTALLED, CHANGED, UPDATE
}
const PLUGIN_STATUS_ICON = [
preload("../../assets/icons/add.png"), preload("../../assets/icons/import_fail.png"),
preload("../../assets/icons/import_check.png"), preload("../../assets/icons/edit_internal.png"),
preload("../../assets/icons/refresh.png")
]
@onready var tree = $Tree
@onready var init_btn = $"%InitBtn"
@onready var check_for_update_btn = $"%CheckForUpdateBtn"
@onready var update_section = $"%UpdateSection"
@onready var force_check = $"%ForceCheck"
@onready var production_check = $"%ProductionCheck"
@onready var update_btn = $"%UpdateBtn"
@onready var loading_overlay = $"%LoadingOverlay"
@onready var loading_label = $"%LoadingLabel"
var gd_plug
var project_dir
var _is_executing = false
var _check_for_update_task_id = -1
func _ready():
project_dir = DirAccess.open("res://")
load_gd_plug()
update_plugin_list(get_plugged_plugins(), get_installed_plugins())
tree.set_column_title(0, "Name")
tree.set_column_title(1, "Arguments")
tree.set_column_title(2, "Status")
connect("visibility_changed", _on_visibility_changed)
func _process(delta):
if not is_instance_valid(gd_plug):
return
if "threadpool" in gd_plug:
gd_plug.threadpool.process(delta)
if _check_for_update_task_id >= 0:
if WorkerThreadPool.is_task_completed(_check_for_update_task_id):
_check_for_update_task_id = -1
show_overlay(false)
disable_ui(false)
func _notification(what):
match what:
NOTIFICATION_PREDELETE:
if is_instance_valid(gd_plug):
gd_plug.threadpool.stop()
gd_plug.free()
NOTIFICATION_APPLICATION_FOCUS_IN:
load_gd_plug()
update_plugin_list(get_plugged_plugins(), get_installed_plugins())
func load_gd_plug():
if is_instance_valid(gd_plug):
gd_plug.free() # Free instance in order to reload script
if project_dir.file_exists("plug.gd"):
init_btn.hide()
check_for_update_btn.show()
update_section.show()
update_btn.show() # Not sure why it is always hidden
var gd_plug_script = load("plug.gd")
gd_plug_script.reload(true) # Reload gd-plug script to get updated
gd_plug = gd_plug_script.new()
gd_plug._plug_start()
gd_plug._plugging()
else:
if project_dir.file_exists("addons/gd-plug/plug.gd"):
init_btn.show()
check_for_update_btn.hide()
update_section.hide()
gd_plug = load("addons/gd-plug/plug.gd").new()
else:
print("Missing dependency: gd-plug")
if is_instance_valid(gd_plug):
emit_signal("gd_plug_loaded", gd_plug)
func update_plugin_list(plugged, installed):
var plugin_names = []
for plugin_name in plugged.keys():
plugin_names.append(plugin_name)
for plugin_name in installed.keys():
if plugin_name in plugin_names:
continue
plugin_names.append(plugin_name)
tree.clear()
tree.create_item() # root
for plugin_name in plugin_names:
var plugin_plugged = plugged.get(plugin_name, {})
var plugin_installed = installed.get(plugin_name, {})
var plugin = plugin_plugged if plugin_name in plugged else plugin_installed
var plugin_status = get_plugin_status(plugin_name)
var plugin_args = []
for plugin_arg in plugin.keys():
var value = plugin[plugin_arg]
if value != null:
if not (value is bool):
if value.is_empty():
continue
else:
continue
match plugin_arg:
"install_root":
plugin_args.append("install root: %s" % str(value))
"include":
plugin_args.append("include %s" % str(value))
"exclude":
plugin_args.append("exclude %s" % str(value))
"branch":
plugin_args.append("branch: %s" % str(value))
"tag":
plugin_args.append("tag: %s" % str(value))
"commit":
plugin_args.append(str(value).left(8))
"dev":
if value:
plugin_args.append("dev")
"on_updated":
plugin_args.append("on_updated: %s" % str(value))
var plugin_args_text = ""
for i in plugin_args.size():
var text = plugin_args[i]
plugin_args_text += text
if i < plugin_args.size() - 1:
plugin_args_text += ", "
var child = tree.create_item(tree.get_root())
child.set_text_alignment(0, HORIZONTAL_ALIGNMENT_LEFT)
child.set_text_alignment(1, HORIZONTAL_ALIGNMENT_CENTER)
child.set_text_alignment(2, HORIZONTAL_ALIGNMENT_CENTER)
child.set_meta("plugin", plugin)
child.set_text(0, plugin_name)
child.set_tooltip_text(0, plugin.url)
child.set_text(1, plugin_args_text)
child.set_tooltip_text(2, PLUGIN_STATUS.keys()[plugin_status].capitalize())
child.set_icon(2, PLUGIN_STATUS_ICON[plugin_status])
func disable_ui(disabled=true):
init_btn.disabled = disabled
check_for_update_btn.disabled = disabled
update_btn.disabled = disabled
func show_overlay(show=true, text=""):
loading_overlay.visible = show
loading_label.text = text
func gd_plug_execute_threaded(name):
if not is_instance_valid(gd_plug):
return
if _is_executing:
return
_is_executing = true
disable_ui(true)
gd_plug._plug_start()
gd_plug._plugging()
gd_plug.call(name)
await gd_plug.threadpool.all_thread_finished
# Make sure to use call_deferred for thread safe function calling while waiting thread to finish
gd_plug._plug_end()
call_deferred("disable_ui", false)
_is_executing = false
clear_environment()
call_deferred("update_plugin_list", get_plugged_plugins(), get_installed_plugins())
func gd_plug_execute(name):
if not is_instance_valid(gd_plug):
return
if _is_executing:
return
_is_executing = true
disable_ui(true)
gd_plug._plug_start()
gd_plug._plugging()
gd_plug.call(name)
gd_plug._plug_end()
disable_ui(false)
_is_executing = false
clear_environment()
update_plugin_list(get_plugged_plugins(), get_installed_plugins())
func clear_environment():
OS.unset_environment("production")
OS.unset_environment("test")
OS.unset_environment("force")
func _on_visibility_changed():
if visible:
load_gd_plug()
update_plugin_list(get_plugged_plugins(), get_installed_plugins())
func _on_Init_pressed():
gd_plug_execute("_plug_init")
load_gd_plug()
func _on_CheckForUpdateBtn_pressed():
var children = tree.get_root().get_children()
if tree.get_root().get_children().size() > 0:
show_overlay(true, "Checking for Updates...")
disable_ui(true)
if _check_for_update_task_id < 0:
var task_id = WorkerThreadPool.add_task(check_for_update.bind(children[0]))
_check_for_update_task_id = (task_id)
func _on_UpdateBtn_pressed():
if force_check.button_pressed:
OS.set_environment("force", "true")
if production_check.button_pressed:
OS.set_environment("production", "true")
show_overlay(true, "Updating...")
gd_plug_execute_threaded("_plug_install")
await gd_plug.threadpool.all_thread_finished
# Make sure to use call_deferred for thread safe function calling while waiting thread to finish
call_deferred("show_overlay", false)
call_deferred("emit_signal", "updated")
func get_plugged_plugins():
return gd_plug._plugged_plugins if is_instance_valid(gd_plug) else {}
func get_installed_plugins():
return gd_plug.installation_config.get_value("plugin", "installed", {}) if is_instance_valid(gd_plug) else {}
func get_plugin_status(plugin_name):
var plugged_plugins = get_plugged_plugins()
var installed_plugins = get_installed_plugins()
var plugin_plugged = plugged_plugins.get(plugin_name, {})
var plugin_installed = installed_plugins.get(plugin_name, {})
var plugin = plugin_plugged if plugin_name in plugged_plugins else plugin_installed
var is_plugged = plugin.name in plugged_plugins
var is_installed = plugin.name in installed_plugins
var changes = gd_plug.compare_plugins(plugin_plugged, plugin_installed) if is_installed else {}
var is_changed = changes.size() > 0
var plugin_status = 0
if is_installed:
if is_plugged:
if is_changed:
plugin_status = 3
else:
plugin_status = 2
else:
plugin_status = 1
else:
plugin_status = 0
return plugin_status
func has_update(plugin):
if not is_instance_valid(gd_plug):
return false
if plugin == null:
return false
var git = gd_plug._GitExecutable.new(ProjectSettings.globalize_path(plugin.plug_dir), gd_plug.logger)
var ahead_behind = []
if git.fetch("origin " + plugin.branch if plugin.branch else "origin").exit == OK:
ahead_behind = git.get_commit_comparison("HEAD", "origin/" + plugin.branch if plugin.branch else "origin")
var is_commit_behind = !!ahead_behind[1] if ahead_behind.size() == 2 else false
if is_commit_behind:
gd_plug.logger.info("%s %d commits behind, update required" % [plugin.name, ahead_behind[1]])
return true
else:
gd_plug.logger.info("%s up to date" % plugin.name)
return false
func check_for_update(child):
var plugin = child.get_meta("plugin")
var plugin_status = get_plugin_status(plugin.name)
if plugin_status == PLUGIN_STATUS.INSTALLED:
var has_update = has_update(plugin)
if has_update:
child.set_icon(2, PLUGIN_STATUS_ICON[PLUGIN_STATUS.UPDATE])
child.set_tooltip_text(2, PLUGIN_STATUS.keys()[PLUGIN_STATUS.UPDATE].capitalize())
if is_instance_valid(child):
var next_child = child.get_next()
if next_child:
check_for_update(next_child)

View file

@ -0,0 +1,112 @@
[gd_scene load_steps=4 format=3 uid="uid://hr5ks54660xu"]
[ext_resource type="Script" path="res://addons/gd-plug-ui/scene/plugin_settings/PluginSettings.gd" id="1"]
[ext_resource type="Texture2D" path="res://addons/gd-plug-ui/assets/icons/progress/progress_animated_texture.tres" id="2_30o7o"]
[sub_resource type="StyleBoxEmpty" id="1"]
[node name="gd-plug" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1")
[node name="Tree" type="Tree" parent="."]
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 0.9
columns = 3
column_titles_visible = true
hide_root = true
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 0
anchor_top = 0.9
anchor_right = 1.0
anchor_bottom = 1.0
theme_override_constants/margin_left = 16
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 16
theme_override_constants/margin_bottom = 8
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
layout_mode = 2
[node name="InitBtn" type="Button" parent="MarginContainer/HBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
size_flags_horizontal = 6
size_flags_vertical = 4
text = "Init"
[node name="CheckForUpdateBtn" type="Button" parent="MarginContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 2
size_flags_vertical = 4
text = "Check for Update"
[node name="UpdateSection" type="HBoxContainer" parent="MarginContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 10
size_flags_vertical = 6
[node name="ForceCheck" type="CheckButton" parent="MarginContainer/HBoxContainer/UpdateSection"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 10
size_flags_vertical = 4
tooltip_text = "Force installation of plugin, may overwrite project files in case of conflicts."
theme_override_styles/focus = SubResource("1")
text = "Force"
[node name="ProductionCheck" type="CheckButton" parent="MarginContainer/HBoxContainer/UpdateSection"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 10
size_flags_vertical = 4
tooltip_text = "Install plugins not marked as \"dev\", and uninstall plugins marked as \"dev\""
theme_override_styles/focus = SubResource("1")
text = "Production"
[node name="UpdateBtn" type="Button" parent="MarginContainer/HBoxContainer/UpdateSection"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 10
size_flags_vertical = 4
text = "Update"
[node name="LoadingOverlay" type="PanelContainer" parent="."]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = -1
anchor_right = 1.0
anchor_bottom = 0.9
grow_horizontal = 2
grow_vertical = 2
metadata/_edit_use_anchors_ = true
[node name="CenterContainer" type="CenterContainer" parent="LoadingOverlay"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="LoadingOverlay/CenterContainer"]
layout_mode = 2
[node name="TextureRect" type="TextureRect" parent="LoadingOverlay/CenterContainer/HBoxContainer"]
layout_mode = 2
texture = ExtResource("2_30o7o")
stretch_mode = 3
[node name="LoadingLabel" type="Label" parent="LoadingOverlay/CenterContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
[connection signal="pressed" from="MarginContainer/HBoxContainer/InitBtn" to="." method="_on_Init_pressed"]
[connection signal="pressed" from="MarginContainer/HBoxContainer/CheckForUpdateBtn" to="." method="_on_CheckForUpdateBtn_pressed"]
[connection signal="pressed" from="MarginContainer/HBoxContainer/UpdateSection/UpdateBtn" to="." method="_on_UpdateBtn_pressed"]

1163
addons/gd-plug/plug.gd Normal file

File diff suppressed because it is too large Load diff

1
icon.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>

After

Width:  |  Height:  |  Size: 994 B

37
icon.svg.import Normal file
View file

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cea4tcn8jcvsh"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

9
plug.gd Normal file
View file

@ -0,0 +1,9 @@
extends "res://addons/gd-plug/plug.gd"
func _plugging():
# Declare plugins with plug(repo, args)
# For example, clone from github repo("user/repo_name")
# plug("imjp94/gd-YAFSM") # By default, gd-plug will only install anything from "addons/" directory
# Or you can explicitly specify which file/directory to include
# plug("imjp94/gd-YAFSM", {"include": ["addons/"]}) # By default, gd-plug will only install anything from "addons/" directory
pass

19
project.godot Normal file
View file

@ -0,0 +1,19 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Godot Template"
config/features=PackedStringArray("4.3", "Forward Plus")
config/icon="res://icon.svg"
[editor_plugins]
enabled=PackedStringArray("res://addons/gd-plug-ui/plugin.cfg")