Skip to content

Commit

Permalink
Integrate Extension Explorer (#910)
Browse files Browse the repository at this point in the history
* Integration of ExtensionExplorer

---------

Co-authored-by: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com>
Co-authored-by: Emmanouil Papadeas <manoschool@yahoo.gr>
  • Loading branch information
3 people authored Jan 23, 2024
1 parent ddce039 commit f43f80c
Show file tree
Hide file tree
Showing 9 changed files with 906 additions and 4 deletions.
28 changes: 25 additions & 3 deletions src/Preferences/PreferencesDialog.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=9 format=3 uid="uid://b3hkjj3s6pe4x"]
[gd_scene load_steps=10 format=3 uid="uid://b3hkjj3s6pe4x"]

[ext_resource type="Script" path="res://src/Preferences/PreferencesDialog.gd" id="1"]
[ext_resource type="Script" path="res://src/Preferences/HandleExtensions.gd" id="2"]
Expand All @@ -7,11 +7,13 @@
[ext_resource type="Script" path="res://src/Preferences/HandleThemes.gd" id="5"]
[ext_resource type="PackedScene" path="res://src/UI/Nodes/ValueSliderV2.tscn" id="7"]
[ext_resource type="Script" path="res://src/UI/Nodes/ValueSlider.gd" id="8"]
[ext_resource type="PackedScene" uid="uid://chy5d42l72crk" path="res://src/UI/ExtensionExplorer/Store.tscn" id="8_jmnx8"]

[sub_resource type="ButtonGroup" id="ButtonGroup_8vsfb"]

[node name="PreferencesDialog" type="AcceptDialog"]
title = "Preferences"
position = Vector2i(0, 36)
size = Vector2i(800, 500)
exclusive = false
popup_window = true
Expand All @@ -28,7 +30,7 @@ offset_bottom = -49.0
size_flags_horizontal = 3
theme_override_constants/separation = 20
theme_override_constants/autohide = 0
split_offset = 150
split_offset = 125

[node name="List" type="ItemList" parent="HSplitContainer"]
custom_minimum_size = Vector2(85, 0)
Expand Down Expand Up @@ -1076,6 +1078,7 @@ tooltip_text = "Specifies the tablet driver being used on Windows. If you have W
mouse_default_cursor_shape = 2

[node name="Extensions" type="VBoxContainer" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide"]
unique_name_in_owner = true
visible = false
layout_mode = 2
script = ExtResource("2")
Expand All @@ -1093,6 +1096,10 @@ text = "Extensions"
layout_mode = 2
size_flags_horizontal = 3

[node name="Explore" type="Button" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/ExtensionsHeader"]
layout_mode = 2
text = "Explore Online"

[node name="InstalledExtensions" type="ItemList" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions"]
layout_mode = 2
auto_height = true
Expand Down Expand Up @@ -1293,7 +1300,18 @@ layout_mode = 2
layout_mode = 2
text = "Pixelorama must be restarted for changes to take effect."

[node name="Popups" type="Node" parent="."]
[node name="Popups" type="Control" parent="."]
layout_mode = 3
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
mouse_filter = 2

[node name="AddExtensionFileDialog" type="FileDialog" parent="Popups"]
mode = 1
Expand All @@ -1307,6 +1325,9 @@ access = 2
filters = PackedStringArray("*.pck ; Godot Resource Pack File", "*.zip ;")
show_hidden_files = true

[node name="Store" parent="Popups" instance=ExtResource("8_jmnx8")]
transient = true

[node name="DeleteConfirmation" type="ConfirmationDialog" parent="."]
unique_name_in_owner = true
position = Vector2i(0, 36)
Expand All @@ -1329,6 +1350,7 @@ vertical_alignment = 1
[connection signal="item_selected" from="HSplitContainer/List" to="." method="_on_List_item_selected"]
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Language/System Language" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Language" method="_on_Language_pressed" binds= [1]]
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Interface/InterfaceOptions/ShrinkContainer/ShrinkApplyButton" to="." method="_on_ShrinkApplyButton_pressed"]
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/ExtensionsHeader/Explore" to="Popups/Store" method="_on_explore_pressed"]
[connection signal="empty_clicked" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/InstalledExtensions" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_InstalledExtensions_empty_clicked"]
[connection signal="item_selected" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/InstalledExtensions" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_InstalledExtensions_item_selected"]
[connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/HBoxContainer/AddExtensionButton" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_AddExtensionButton_pressed"]
Expand Down
185 changes: 185 additions & 0 deletions src/UI/ExtensionExplorer/Entry/ExtensionEntry.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
class_name ExtensionEntry
extends Panel

var extension_container: VBoxContainer
var thumbnail := ""
var download_link := ""
var download_path := ""
var tags := PackedStringArray()
var is_update := false ## An update instead of download

# node references used in this script
@onready var ext_name := %ExtensionName as Label
@onready var ext_discription := %ExtensionDescription as TextEdit
@onready var small_picture := %Picture as TextureButton
@onready var enlarged_picture := %Enlarged as TextureRect
@onready var request_delay := %RequestDelay as Timer
@onready var thumbnail_request := %ImageRequest as HTTPRequest
@onready var extension_downloader := %DownloadRequest as HTTPRequest
@onready var down_button := %DownloadButton as Button
@onready var progress_bar := %ProgressBar as ProgressBar
@onready var done_label := %Done as Label
@onready var alert_dialog := %Alert as AcceptDialog


func set_info(info: Dictionary, extension_path: String) -> void:
if "name" in info.keys() and "version" in info.keys():
ext_name.text = str(info["name"], "-v", info["version"])
# check for updates
change_button_if_updatable(info["name"], info["version"])
# Setting path extension will be "temporarily" downloaded to before install
DirAccess.make_dir_recursive_absolute(str(extension_path, "Download/"))
download_path = str(extension_path, "Download/", info["name"], ".pck")
if "description" in info.keys():
ext_discription.text = info["description"]
ext_discription.tooltip_text = ext_discription.text
if "thumbnail" in info.keys():
thumbnail = info["thumbnail"]
if "download_link" in info.keys():
download_link = info["download_link"]
if "tags" in info.keys():
tags.append_array(info["tags"])

# Adding a tiny delay to prevent sending bulk requests
request_delay.wait_time = randf() * 2
request_delay.start()


func _on_RequestDelay_timeout() -> void:
request_delay.queue_free() # node no longer needed
thumbnail_request.request(thumbnail) # image


func _on_ImageRequest_request_completed(
_result, _response_code, _headers, body: PackedByteArray
) -> void:
# Update the received image
thumbnail_request.queue_free()
var image := Image.new()
# for images on internet there is a hagh chance that extension is wrong
# so check all of them even if they give error
var err := image.load_png_from_buffer(body)
if err != OK:
var err_a := image.load_jpg_from_buffer(body)
if err_a != OK:
var err_b := image.load_webp_from_buffer(body)
if err_b != OK:
var err_c := image.load_tga_from_buffer(body)
if err_c != OK:
image.load_bmp_from_buffer(body)
var texture := ImageTexture.create_from_image(image)
small_picture.texture_normal = texture
small_picture.pressed.connect(enlarge_thumbnail.bind(texture))


func _on_Download_pressed() -> void:
down_button.disabled = true
extension_downloader.download_file = download_path
extension_downloader.request(download_link)
prepare_progress()


## Called after the extension downloader has finished its job
func _on_DownloadRequest_request_completed(
result: int, _response_code: int, _headers: PackedStringArray, _body: PackedByteArray
) -> void:
if result == HTTPRequest.RESULT_SUCCESS:
# Add extension
extension_container.install_extension(download_path)
if is_update:
is_update = false
announce_done(true)
else:
alert_dialog.get_node("Text").text = (
str(
"Unable to Download extension...\nHttp Code: ",
result,
" (",
error_string(result),
")"
)
. c_unescape()
)
alert_dialog.popup_centered()
announce_done(false)
DirAccess.remove_absolute(download_path)


## Updates the entry node's UI
func announce_done(success: bool) -> void:
close_progress()
down_button.disabled = false
if success:
done_label.visible = true
down_button.text = "Re-Download"
done_label.get_node("DoneDelay").start()


## Returns true if entry contains ALL tags in tag_array
func tags_match(tag_array: PackedStringArray) -> bool:
if tags.size() > 0:
for tag in tag_array:
if !tag in tags:
return false
return true
else:
if tag_array.size() > 0:
return false
return true


## Updates the entry node's UI if it has an update available
func change_button_if_updatable(extension_name: String, new_version: float) -> void:
for extension in extension_container.extensions.keys():
if extension_container.extensions[extension].file_name == extension_name:
var old_version = str_to_var(extension_container.extensions[extension].version)
if typeof(old_version) == TYPE_FLOAT:
if new_version > old_version:
down_button.text = "Update"
is_update = true
elif new_version == old_version:
down_button.text = "Re-Download"


## Show an enlarged version of the thumbnail
func enlarge_thumbnail(texture: ImageTexture) -> void:
enlarged_picture.texture = texture
enlarged_picture.get_parent().popup_centered()


## A beautification function that hides the "Done" label bar after some time
func _on_DoneDelay_timeout() -> void:
done_label.visible = false


## Progress bar method
func prepare_progress() -> void:
progress_bar.visible = true
progress_bar.value = 0
progress_bar.get_node("ProgressTimer").start()


## Progress bar method
func update_progress() -> void:
var down := extension_downloader.get_downloaded_bytes()
var total := extension_downloader.get_body_size()
progress_bar.value = (float(down) / float(total)) * 100.0


## Progress bar method
func close_progress() -> void:
progress_bar.visible = false
progress_bar.get_node("ProgressTimer").stop()


## Progress bar method
func _on_ProgressTimer_timeout() -> void:
update_progress()


func _manage_enlarded_thumbnail_close() -> void:
enlarged_picture.get_parent().hide()


func _manage_alert_close() -> void:
alert_dialog.hide()
125 changes: 125 additions & 0 deletions src/UI/ExtensionExplorer/Entry/ExtensionEntry.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
[gd_scene load_steps=3 format=3 uid="uid://dnjpemuehkxsn"]

[ext_resource type="Script" path="res://src/UI/ExtensionExplorer/Entry/ExtensionEntry.gd" id="1_3no3v"]
[ext_resource type="Texture2D" uid="uid://b47r0c6auaqk6" path="res://assets/graphics/icons/icon.png" id="2_qhsve"]

[node name="ExtensionEntry" type="Panel"]
self_modulate = Color(0.411765, 0.411765, 0.411765, 1)
custom_minimum_size = Vector2(300, 150)
offset_right = 284.0
offset_bottom = 150.0
size_flags_horizontal = 3
script = ExtResource("1_3no3v")

[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2

[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
layout_mode = 2

[node name="Picture" type="TextureButton" parent="MarginContainer/HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(120, 120)
layout_mode = 2
mouse_default_cursor_shape = 2
texture_normal = ExtResource("2_qhsve")
ignore_texture_size = true
stretch_mode = 5

[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3

[node name="ExtensionName" type="Label" parent="MarginContainer/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Extension Name..."

[node name="ExtensionDescription" type="TextEdit" parent="MarginContainer/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
placeholder_text = "Description"
editable = false
wrap_mode = 1

[node name="Done" type="Label" parent="MarginContainer/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
visible = false
self_modulate = Color(0.337255, 1, 0, 1)
layout_mode = 2
text = "Done!!!"

[node name="DoneDelay" type="Timer" parent="MarginContainer/HBoxContainer/VBoxContainer/Done"]
wait_time = 2.0

[node name="ProgressBar" type="ProgressBar" parent="MarginContainer/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(0, 20)
layout_mode = 2

[node name="ProgressTimer" type="Timer" parent="MarginContainer/HBoxContainer/VBoxContainer/ProgressBar"]
wait_time = 0.1

[node name="DownloadButton" type="Button" parent="MarginContainer/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Download"

[node name="RequestDelay" type="Timer" parent="."]
unique_name_in_owner = true
one_shot = true
autostart = true

[node name="ImageRequest" type="HTTPRequest" parent="."]
unique_name_in_owner = true

[node name="DownloadRequest" type="HTTPRequest" parent="."]
unique_name_in_owner = true

[node name="Alert" type="AcceptDialog" parent="."]
unique_name_in_owner = true
size = Vector2i(421, 106)

[node name="Text" type="Label" parent="Alert"]
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
horizontal_alignment = 1

[node name="EnlardedThumbnail" type="Window" parent="."]
position = Vector2i(0, 36)
size = Vector2i(440, 360)
visible = false
transient = true
exclusive = true

[node name="Enlarged" type="TextureRect" parent="EnlardedThumbnail"]
unique_name_in_owner = true
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
stretch_mode = 5

[connection signal="timeout" from="MarginContainer/HBoxContainer/VBoxContainer/Done/DoneDelay" to="." method="_on_DoneDelay_timeout"]
[connection signal="timeout" from="MarginContainer/HBoxContainer/VBoxContainer/ProgressBar/ProgressTimer" to="." method="_on_ProgressTimer_timeout"]
[connection signal="pressed" from="MarginContainer/HBoxContainer/VBoxContainer/DownloadButton" to="." method="_on_Download_pressed"]
[connection signal="timeout" from="RequestDelay" to="." method="_on_RequestDelay_timeout"]
[connection signal="request_completed" from="ImageRequest" to="." method="_on_ImageRequest_request_completed"]
[connection signal="request_completed" from="DownloadRequest" to="." method="_on_DownloadRequest_request_completed"]
[connection signal="close_requested" from="Alert" to="." method="_manage_alert_close"]
[connection signal="focus_exited" from="Alert" to="." method="_manage_alert_close"]
[connection signal="close_requested" from="EnlardedThumbnail" to="." method="_manage_enlarded_thumbnail_close"]
[connection signal="focus_exited" from="EnlardedThumbnail" to="." method="_manage_enlarded_thumbnail_close"]
Loading

0 comments on commit f43f80c

Please sign in to comment.