diff --git a/Lua/Plugins/test.gd b/Lua/Plugins/test.gd
deleted file mode 100644
index e08925d..0000000
--- a/Lua/Plugins/test.gd
+++ /dev/null
@@ -1,11 +0,0 @@
-extends Node
-
-
-# Called when the node enters the scene tree for the first time.
-func _ready():
- pass # Replace with function body.
-
-
-# Called every frame. 'delta' is the elapsed time since the previous frame.
-func _process(delta):
- pass
diff --git a/Lua/test.gd b/Lua/test.gd
deleted file mode 100644
index e08925d..0000000
--- a/Lua/test.gd
+++ /dev/null
@@ -1,11 +0,0 @@
-extends Node
-
-
-# Called when the node enters the scene tree for the first time.
-func _ready():
- pass # Replace with function body.
-
-
-# Called every frame. 'delta' is the elapsed time since the previous frame.
-func _process(delta):
- pass
diff --git a/README.md b/README.md
index 17f457b..90c3b3b 100644
--- a/README.md
+++ b/README.md
@@ -59,11 +59,11 @@ To extend the functionality of GriddyCode for a specific **file extension**, cre
| Method | Example | Description | Notes |
| -------- | -------- | -------- | -------- |
-| `highlight(keyword: String, color: String)` | `highlight("const", "reserved")` | Tells GriddyCode to highlight a certain keyword with a preset of colors. | Available colors: `reserved`, `string`, `binary`, `symbol`, `variable`, `operator`, `comments`, `error`, `function`, `member` |
+| `highlight(keyword: String, color: String)` | `highlight("const", "reserved")` | Tells GriddyCode to highlight a certain keyword with a preset of colors. | Available colors: `reserved`, `annotation`, `string`, `binary`, `symbol`, `variable`, `operator`, `comments`, `error`, `function`, `member` |
| `highlight_region(start: String, end: String, color: String, line_only: bool = false)` | `highlight("/*", "*/", "comments", false)` | Tells GriddyCode to highlight a region with a preset of colors. | The `start` must be a symbol. Due to Godot's limited functionality, you can't use RegEx. |
| `add_comment(comment: String)` | `add_comment("What is blud doing 🗣️🗣️🗣️")` | Adds a comment to be randomly chosen in the `CTRL` + `L` menu. | The username, profile picture, date, and likes are chosen by GriddyCode. |
-| `detect_functions(content: String) -> Array[String]` | `detect_functions("const test = 3; function main() {}; async init() => { main() }")` | Called by GriddyCode upon input. Results are showed in the autocomplete feature. | This must be provided by the Lua script. It must return an array of strings (i.e. ["main", "init"]). |
-| `detect_variables(content: String) -> Array[String]` | `detect_variables("const test = 3;")` | Called by GriddyCode upon input. Results are showed in the autocomplete feature. | This must be provided by the Lua script. It must return an array of strings (i.e. ["test"]). |
+| `detect_functions(content: String, line: int, column: int) -> Array[String]` | `detect_functions("const test = 3; function main() {}; async init() => { main() }")` | Called by GriddyCode upon input. Results are showed in the autocomplete feature. | This must be provided by the Lua script. It must return an array of strings (i.e. ["main", "init"]). "line" and "column" are the position of the cursor when the autocomplete was requested. |
+| `detect_variables(content: String, line: int, column: int) -> Array[String]` | `detect_variables("const test = 3;")` | Called by GriddyCode upon input. Results are showed in the autocomplete feature. | This must be provided by the Lua script. It must return an array of strings (i.e. ["test"]). "line" and "column" are the position of the cursor when the autocomplete was requested. |
*Note: to provide reserved variables/functions (i.e. `Math`/`parseInt()` in JS) you can have them already set up in the array you return. GriddyCode will handle the rest!*
diff --git a/Scenes/comments.tscn b/Scenes/comments.tscn
index 3d3b5df..74a91da 100644
--- a/Scenes/comments.tscn
+++ b/Scenes/comments.tscn
@@ -22,7 +22,7 @@ script = ExtResource("1_8hvfh")
[node name="ColorRect" type="ColorRect" parent="."]
material = SubResource("ShaderMaterial_onjnb")
layout_mode = 0
-offset_right = 392.0
+offset_right = 429.0
offset_bottom = 534.0
color = Color(0, 0, 0, 1)
diff --git a/Scenes/editor.tscn b/Scenes/editor.tscn
index a8ba1e2..161ee01 100644
--- a/Scenes/editor.tscn
+++ b/Scenes/editor.tscn
@@ -101,10 +101,11 @@ script = ExtResource("2_7x3ll")
[node name="Background" type="ColorRect" parent="."]
unique_name_in_owner = true
-visible = false
modulate = Color(1, 1, 1, 0)
-offset_right = 1920.0
-offset_bottom = 1080.0
+offset_left = -368.0
+offset_top = -207.0
+offset_right = 2263.0
+offset_bottom = 1342.0
[node name="FileDialog" type="RichTextLabel" parent="."]
unique_name_in_owner = true
@@ -136,40 +137,6 @@ script = ExtResource("5_bhd70")
wait_time = 5.0
autostart = true
-[node name="Intro" type="Node2D" parent="."]
-unique_name_in_owner = true
-visible = false
-
-[node name="RichTextLabel" type="RichTextLabel" parent="Intro"]
-offset_left = 836.0
-offset_top = 112.0
-offset_right = 3336.0
-offset_bottom = 2112.0
-scale = Vector2(0.235, 0.235)
-theme_override_font_sizes/normal_font_size = 376
-bbcode_enabled = true
-text = "Greetings!"
-
-[node name="RichTextLabel2" type="RichTextLabel" parent="Intro"]
-offset_left = 841.0
-offset_top = 244.0
-offset_right = 3341.0
-offset_bottom = 2244.0
-scale = Vector2(0.235, 0.235)
-theme_override_font_sizes/normal_font_size = 146
-bbcode_enabled = true
-text = "You're currently using [color=#c9daf8]Bussin[/color] [color=#85c6ff]GriddyCode[/color]"
-
-[node name="RichTextLabel3" type="RichTextLabel" parent="Intro"]
-offset_left = 841.0
-offset_top = 380.0
-offset_right = 3341.0
-offset_bottom = 2380.0
-scale = Vector2(0.235, 0.235)
-theme_override_font_sizes/normal_font_size = 106
-bbcode_enabled = true
-text = "To get started, please choose a file."
-
[node name="Settings" type="Node2D" parent="."]
unique_name_in_owner = true
diff --git a/Scenes/update.tscn b/Scenes/update.tscn
new file mode 100644
index 0000000..88fc5d1
--- /dev/null
+++ b/Scenes/update.tscn
@@ -0,0 +1,50 @@
+[gd_scene load_steps=3 format=3 uid="uid://bkx02j85qa1rm"]
+
+[ext_resource type="Script" path="res://Scripts/update.gd" id="1_ug1sp"]
+[ext_resource type="Script" path="res://Scripts/hyperlink.gd" id="2_w1buf"]
+
+[node name="Control" 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_ug1sp")
+
+[node name="RichTextLabel" type="RichTextLabel" parent="."]
+layout_mode = 0
+offset_top = 23.0
+offset_right = 256.0
+offset_bottom = 63.0
+text = "Current version: v1.0.3"
+
+[node name="Button" type="Button" parent="."]
+layout_mode = 0
+offset_top = 56.0
+offset_right = 257.0
+offset_bottom = 108.0
+text = "💾 Check updates"
+
+[node name="HSeparator" type="HSeparator" parent="."]
+layout_mode = 0
+offset_top = 7.0
+offset_right = 271.0
+offset_bottom = 11.0
+
+[node name="RichTextLabel2" type="RichTextLabel" parent="."]
+visible = false
+layout_mode = 0
+offset_left = 294.0
+offset_top = 58.0
+offset_right = 765.0
+offset_bottom = 98.0
+bbcode_enabled = true
+text = "Nothing new..."
+scroll_active = false
+script = ExtResource("2_w1buf")
+
+[node name="HTTPRequest" type="HTTPRequest" parent="."]
+use_threads = true
+
+[connection signal="pressed" from="Button" to="." method="_on_button_pressed"]
diff --git a/Scripts/file_dialog.gd b/Scripts/file_dialog.gd
index 5281b46..f927fe1 100644
--- a/Scripts/file_dialog.gd
+++ b/Scripts/file_dialog.gd
@@ -17,6 +17,8 @@ signal ui_close
func change_dir(path) -> void:
if !dir: dir = DirAccess.open(path)
+ #dir.include_hidden = true
+ # WARNING: this will heavily affect performance if de-commented
dirs = [".."];
dirs.append_array(dir.get_directories())
@@ -30,7 +32,7 @@ func change_dir(path) -> void:
%Cam.focus_on(gp(), zoom)
func setup() -> void:
- active = true
+ active = false
change_dir(editor.current_dir)
update_ui()
@@ -66,10 +68,12 @@ func show_item(item: String) -> void:
else:
push_bgcolor(Color(0, 0, 0, 0)) # Reset background color if not selected
+ var is_dir = dir.get_directories().find(item) != -1;
+
if item == "..":
push_color(LuaSingleton.gui.font_color)
add_text("")
- elif dir.get_directories().find(item) != -1:
+ elif is_dir:
push_color(LuaSingleton.gui.completion_selected_color)
add_text("")
else:
@@ -80,9 +84,22 @@ func show_item(item: String) -> void:
add_text(data.icon)
pop()
- add_text(" " + item + '\n')
- if active: %Cam.focus_on(Vector2(gp().x, global_position.y + (selected_index * 30)), zoom)
+ var filename = item.split(".")[0];
+
+ if is_dir: filename = item
+
+ if filename.length() > 30:
+ filename = filename.left(30) + "..." + filename.right(3)
+
+ if item == "..":
+ add_text(" %s\n" % [ item ])
+ elif is_dir or !item.contains("."):
+ add_text(" %s\n" % [ filename ] )
+ else:
+ add_text(" %s.%s\n" % [ filename, item.split(".")[1] ] )
+
+ if active: %Cam.focus_on(Vector2(gp().x, global_position.y + (selected_index * 23)), zoom)
# i gave up at that point, sorry for what you're about to witness
func is_selected(item: String) -> bool:
@@ -105,10 +122,13 @@ func handle_enter_key() -> void:
editor.current_dir = dir.get_current_dir();
editor.open_file(editor.current_dir + "/" + item)
- %Intro.hide()
LuaSingleton.setup_extension(item.split(".")[-1])
code.setup_highlighter()
+ get_tree().create_timer(.1).timeout.connect(func():
+ code.grab_focus()
+ )
+
ui_close.emit()
else:
selected_index = 0;
diff --git a/Scripts/file_manager.gd b/Scripts/file_manager.gd
index 8fbd253..fde026c 100644
--- a/Scripts/file_manager.gd
+++ b/Scripts/file_manager.gd
@@ -9,14 +9,37 @@ const NOTICE = preload("res://Scenes/notice.tscn")
var current_file: String;
var current_dir: String = "/";
+var time_start = 0
+var time_now = 0
+
func _ready():
- if (OS.get_name() == "Windows"):
+ if LuaSingleton.discord_sdk:
+ DiscordSDK.app_id = 1220393467738591242 # Application ID
+
+ DiscordSDK.large_image = "griddycode" # Image key from "Art Assets"
+ DiscordSDK.large_image_text = "https://github.com/face-hh/griddycode"
+ DiscordSDK.start_timestamp = int(Time.get_unix_time_from_system())
+
+ if OS.get_name() == "Windows":
current_dir = "C:/"
+ var args = OS.get_cmdline_args()
+ var is_debug = OS.is_debug_build()
+ var path = OS.get_executable_path().get_base_dir()
+
+ if args.size() > 0 and !is_debug:
+ if args[0] != ".":
+ current_file = path + "/" + args[0]
+ current_dir = path
+
+ var is_cli = args.size() > 0 and !is_debug
+
+ print("INFO: Running inside CLI mode: ", is_cli)
+
inject_lua()
check_for_reserved()
- load_game()
+ load_game(is_cli)
open_file(current_file)
LuaSingleton.themes = list_themes()
@@ -27,8 +50,8 @@ func _ready():
file_dialog.setup()
if !current_file:
+ LuaSingleton.setup_discord_sdk("Idle", "")
Code.toggle(%FileDialog)
- %Intro.show()
warn("Welcome to [color=#c9daf8]Bussin[/color] [color=#85c6ff]GriddyCode[/color]! Please select a file, then press CTRL + I to get started! :D")
func check_for_reserved() -> void:
@@ -40,7 +63,6 @@ func check_for_reserved() -> void:
func _on_file_dialog_file_selected(path: String) -> void:
open_file(path)
- %Intro.hide()
func inject_lua() -> void:
DirAccess.make_dir_absolute("user://themes")
@@ -54,15 +76,21 @@ func inject_lua() -> void:
for plugin in plugins:
copy_if_not_exist("langs", "Plugins", plugin)
+func copy_from_res(from: String, to: String) -> void:
+ var file_from = FileAccess.open(from, FileAccess.READ)
+ var file_to = FileAccess.open(to, FileAccess.WRITE)
+ file_to.store_buffer(file_from.get_buffer(file_from.get_length()))
+ file_to = null
+ file_from = null
+
func copy_if_not_exist(user_path: String, res_path: String, file: String) -> void:
if !file.contains("lua"): return
var path = "user://" + user_path + "/" + file;
var current_path = "res://Lua/" + res_path + "/" + file;
- var exists = FileAccess.file_exists(path);
- if !exists:
- DirAccess.copy_absolute(current_path, path)
+ DirAccess.remove_absolute(path)
+ copy_from_res(current_path, path)
func warn(notice: String) -> void:
var node = NOTICE.instantiate()
@@ -76,6 +104,8 @@ func warn(notice: String) -> void:
)
func open_file(path: String) -> void:
+ LuaSingleton.setup_discord_sdk("Editing " + path.split("/")[-1], "In " + current_dir.split("/")[-1])
+
var src = Fs._load(path)
Code.text = src
@@ -100,6 +130,8 @@ func _notification(what):
"settings": LuaSingleton.settings,
"theme": LuaSingleton.theme
}
+
+
save_data(save_dict)
Fs.save(current_file, Code.text)
@@ -115,7 +147,7 @@ func save_data(dict: Dictionary):
save_game.store_line(json_string)
-func load_game():
+func load_game(cli: bool = false):
if not FileAccess.file_exists("user://data.save"):
return # Error! We don't have a save to load.
@@ -132,11 +164,14 @@ func load_game():
var node_data = json.get_data()
- current_dir = node_data["current_dir"]
- current_file = node_data["current_file"]
+ if !cli:
+ current_dir = node_data["current_dir"]
+ current_file = node_data["current_file"]
+
LuaSingleton.theme = node_data["theme"]
- var settings = node_data["settings"];
+ var settings = node_data["settings"]
+ var new_settings = []
for dic: Dictionary in settings:
LuaSingleton.handle_internal_setting_change(dic.property, dic.value)
@@ -148,12 +183,16 @@ func load_game():
return
LuaSingleton.settings.remove_at(index)
- LuaSingleton.settings.append(dic);
+ new_settings.append(dic)
- LuaSingleton.settings = node_data["settings"]
+ for setting in LuaSingleton.settings:
+ if not new_settings.has(setting):
+ new_settings.append(setting)
+ LuaSingleton.settings = new_settings
LuaSingleton.on_settings_change.emit()
+
func _on_auto_save_timer_timeout():
if !current_file: return
if !Code.file_modified: return
diff --git a/Scripts/lua_singleton.gd b/Scripts/lua_singleton.gd
index 3c92351..fca2397 100644
--- a/Scripts/lua_singleton.gd
+++ b/Scripts/lua_singleton.gd
@@ -3,6 +3,9 @@ extends Node
var themes: Array = ["One Dark Pro Darker"];
var theme: String = "One Dark Pro Darker"; # default
+# TODO: change me each version
+var version: String = "v1.1.0";
+
var gui: Dictionary = {
"background_color": str_to_clr("#23272e"),
"current_line_color": str_to_clr("#23272e"),
@@ -175,25 +178,35 @@ var settings: Array = [
"unit": "%",
"min": 0, "max": 100,
},
+ {
+ "property": "discord_sdk",
+ "display": "Discord SDK",
+ "options": [],
+ "icon": "",
+ "value": true,
+ },
];
var keywords: Dictionary = {
- "reserved": str_to_clr("c678cc"),
- "string": str_to_clr("98c379"),
- "binary": str_to_clr("d19a66"),
- "symbol": str_to_clr("839fb6"),
- "variable": str_to_clr("e5c07b"),
- "operator": str_to_clr("56b6c2"),
- "comments": str_to_clr("7f848e"),
- "error": str_to_clr("d31820"),
- "function": str_to_clr("437ed9"),
- "member": str_to_clr("e06c75")
+ "reserved": str_to_clr("c678cc"),
+ "annotation": str_to_clr("a2b429"),
+ "string": str_to_clr("98c379"),
+ "binary": str_to_clr("d19a66"),
+ "symbol": str_to_clr("839fb6"),
+ "variable": str_to_clr("e5c07b"),
+ "operator": str_to_clr("56b6c2"),
+ "comments": str_to_clr("7f848e"),
+ "error": str_to_clr("d31820"),
+ "function": str_to_clr("437ed9"),
+ "member": str_to_clr("e06c75")
}
var keywords_to_highlight: Dictionary = {}
var color_regions_to_highlight: Array = []
var comments: Array = []
+var discord_sdk: bool = true;
+
const SUNLIGHT = preload("res://Shaders/sunlight.gdshader")
const VHS_AND_CRT = preload("res://Shaders/vhs_and_crt.gdshader")
@@ -277,6 +290,15 @@ func handle_internal_setting_change(property: String, value: Variant) -> void:
Music.set_enabled(value)
if p == "music_volume":
Music.set_volume(value)
+ if p == "discord_sdk":
+ discord_sdk = value;
+
+func setup_discord_sdk(detail: String, state: String) -> void:
+ if !discord_sdk: return
+ DiscordSDK.details = detail
+ DiscordSDK.state = state
+
+ DiscordSDK.refresh()
# LUA
var lua: LuaAPI = LuaAPI.new()
@@ -324,10 +346,6 @@ func _trim(input: String):
return input.strip_edges()
func setup_extension(extension):
- keywords_to_highlight = {}
- color_regions_to_highlight = []
- comments = []
-
# FILE EXTENSIONS
lua.bind_libraries(["base", "table", "string"])
diff --git a/Scripts/music.gd b/Scripts/music.gd
index 157da25..d15d682 100644
--- a/Scripts/music.gd
+++ b/Scripts/music.gd
@@ -17,7 +17,7 @@ var SONGS = [
var data: Array;
var iter: int;
-var enabled: bool = true;
+var enabled: bool = false;
func _ready():
play_random_song()
diff --git a/Scripts/settings.gd b/Scripts/settings.gd
index 87247c2..6acb160 100644
--- a/Scripts/settings.gd
+++ b/Scripts/settings.gd
@@ -1,15 +1,13 @@
extends CodeEdit
@onready var code: CodeEdit = %Code
+@onready var editor: FileManager = $".."
const VARIABLE = preload("res://Icons/variable.png")
const FUNCTION = preload("res://Icons/function.png")
@onready var rich_text_labels: Array[RichTextLabel] = [
%FileDialog,
- $"../Intro/RichTextLabel",
- $"../Intro/RichTextLabel2",
- $"../Intro/RichTextLabel3"
];
var file_modified = false;
@@ -19,6 +17,8 @@ var active_overlay: Variant;
var node_is_transitioning: bool;
func _ready() -> void:
+ grab_focus()
+
LuaSingleton.on_theme_load.connect(setup_theme)
tween_fade(%FileDialog, 0)
@@ -64,12 +64,14 @@ func setup_highlighter() -> void:
CH.add_keyword_color(key, LuaSingleton.keywords[kth[key]])
for entry in crth:
+ if CH.has_color_region(entry[0]): continue
+
CH.add_color_region(entry[0], entry[1], LuaSingleton.keywords[entry[2]], entry[3])
# CodeEdit functionality
func _on_code_completion_requested() -> void:
- var function_names = LuaSingleton.lua.call_function("detect_functions", [text])
- var variable_names = LuaSingleton.lua.call_function("detect_variables", [text])
+ var function_names = LuaSingleton.lua.call_function("detect_functions", [text, get_caret_line(), get_caret_column()])
+ var variable_names = LuaSingleton.lua.call_function("detect_variables", [text, get_caret_line(), get_caret_column()])
if typeof(function_names) == Variant.Type.TYPE_ARRAY:
for each in function_names:
@@ -105,6 +107,9 @@ func toggle(node: Object, apply_background: bool = true, factor: float = (18 * 7
if node is FileDialogType:
node.active = !_show;
+ if _show && !editor.current_file:
+ editor.warn("[color=yellow]WARNING[/color]: You are currently in an empty file. No autosave will be performed.")
+
if apply_background:
tween_fade(%Background, opacity, !_show)
elif not apply_background and !_show:
@@ -112,7 +117,8 @@ func toggle(node: Object, apply_background: bool = true, factor: float = (18 * 7
if _show:
%Cam.focus_die()
- code.grab_focus()
+ if !node is FileDialogType:
+ code.grab_focus()
else:
if node.name == "Info":
future_pos.x += 700
@@ -183,7 +189,7 @@ func get_longest_line(lines: Array = text.split("\n")) -> String:
return longestLine
-func _process(delta):
+func _process(_delta):
if Input.is_action_just_pressed("ui_open"): toggle(%FileDialog)
if Input.is_action_just_pressed("ui_settings"): toggle(%Settings, true, (18 * 7.5) * 2)
if Input.is_action_just_pressed("ui_info"): toggle(%Info, true, 1500)
@@ -191,7 +197,7 @@ func _process(delta):
if Input.is_action_just_pressed("ui_cancel"): toggle(%FileDialog)
if Input.is_action_just_pressed("ui_comments"): toggle(%Comments, false, -(18 * 7.5))
-func _on_gui_input(event):
+func _on_gui_input(_event):
if Input.is_action_just_pressed("ui_open"): accept_event(); toggle(%FileDialog)
if Input.is_action_just_pressed("ui_settings"): accept_event(); toggle(%Settings, true, (18 * 7.5) * 2)
if Input.is_action_just_pressed("ui_info"): accept_event(); toggle(%Info, true, 1500)
diff --git a/Scripts/settings_list.gd b/Scripts/settings_list.gd
index 76b5971..836c445 100644
--- a/Scripts/settings_list.gd
+++ b/Scripts/settings_list.gd
@@ -1,6 +1,7 @@
extends VBoxContainer
const SETTING = preload("res://Scenes/setting.tscn")
+const UPDATE = preload("res://Scenes/update.tscn")
# Called when the node enters the scene tree for the first time.
func _ready():
@@ -22,6 +23,10 @@ func setup_settings() -> void:
create_setting(setting.display, setting.icon, setting.value, setting.options, setting.property, unit, _min, _max, precision)
+ var child = UPDATE.instantiate()
+
+ add_child(child)
+
func create_setting(text: String, icon: String, value: Variant, options: Array, property: String, unit: String, _min: float, _max: float, precision: bool) -> void:
var node = SETTING.instantiate()
diff --git a/Scripts/update.gd b/Scripts/update.gd
new file mode 100644
index 0000000..b29e20c
--- /dev/null
+++ b/Scripts/update.gd
@@ -0,0 +1,50 @@
+extends Control
+
+@onready var info: RichTextLabel = $RichTextLabel2
+@onready var current_version: RichTextLabel = $RichTextLabel
+
+var is_requesting = false;
+
+func _ready():
+ current_version.text = "Current version: " + LuaSingleton.version
+ $HTTPRequest.request_completed.connect(_on_request_completed)
+
+func _on_button_pressed():
+ if is_requesting: return
+
+ $HTTPRequest.request("https://api.github.com/repos/face-hh/griddycode/releases/latest")
+ is_requesting = true
+
+ info.show()
+
+ info.text = "Loading..."
+
+func _on_request_completed(_result, _response_code, _headers, body):
+ info.clear()
+
+ var json = JSON.parse_string(body.get_string_from_utf8())
+ if !is_higher_version(json["name"]):
+ info.text = "Nothing new, you're up to date! 🦗"
+ else:
+ info.text = "Great, [color=green]%s[/color] is available! Head over to [url=https://github.com/face-hh/griddycode/releases]our GitHub repository[/url] to download it! 🎉" % json["name"]
+
+ info.show()
+
+ is_requesting = false
+
+ get_tree().create_timer(10).timeout.connect(info.hide)
+
+func is_higher_version(new_version: String) -> bool:
+ var current_components = LuaSingleton.version.replace("v", "").split(".")
+ var new_components = new_version.replace("v", "").split(".")
+
+ for i in range(3):
+ var current_num = current_components[i]
+ var new_num = new_components[i]
+
+ if new_num > current_num:
+ return true
+ elif new_num < current_num:
+ return false
+
+ return false # Same version if we reach here
diff --git a/addons/anthonyec.camera_preview/GuiResizerTopLeft.svg b/addons/anthonyec.camera_preview/GuiResizerTopLeft.svg
deleted file mode 100644
index fe4dbf5..0000000
--- a/addons/anthonyec.camera_preview/GuiResizerTopLeft.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/addons/anthonyec.camera_preview/GuiResizerTopRight.svg b/addons/anthonyec.camera_preview/GuiResizerTopRight.svg
deleted file mode 100644
index dd00953..0000000
--- a/addons/anthonyec.camera_preview/GuiResizerTopRight.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/addons/anthonyec.camera_preview/Pin.svg b/addons/anthonyec.camera_preview/Pin.svg
deleted file mode 100644
index 8e5935c..0000000
--- a/addons/anthonyec.camera_preview/Pin.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/addons/anthonyec.camera_preview/plugin.cfg b/addons/anthonyec.camera_preview/plugin.cfg
deleted file mode 100644
index 4ad0d4c..0000000
--- a/addons/anthonyec.camera_preview/plugin.cfg
+++ /dev/null
@@ -1,7 +0,0 @@
-[plugin]
-
-name="Little Camera Preview"
-description="Shows a picture-in-picture preview of the selected 2D or 3D camera"
-author="Anthony Cossins"
-version="1.3"
-script="plugin.gd"
diff --git a/addons/anthonyec.camera_preview/plugin.gd b/addons/anthonyec.camera_preview/plugin.gd
deleted file mode 100644
index 4e74dd8..0000000
--- a/addons/anthonyec.camera_preview/plugin.gd
+++ /dev/null
@@ -1,87 +0,0 @@
-@tool
-extends EditorPlugin
-
-const preview_scene = preload("res://addons/anthonyec.camera_preview/preview.tscn")
-
-var preview: CameraPreview
-var current_main_screen_name: String
-
-func _enter_tree() -> void:
- main_screen_changed.connect(_on_main_screen_changed)
- EditorInterface.get_selection().selection_changed.connect(_on_editor_selection_changed)
-
- # Initialise preview panel and add to main screen.
- preview = preview_scene.instantiate() as CameraPreview
- preview.request_hide()
-
- var main_screen = EditorInterface.get_editor_main_screen()
- main_screen.add_child(preview)
-
-func _exit_tree() -> void:
- if preview:
- preview.queue_free()
-
-func _ready() -> void:
- # TODO: Currently there is no API to get the main screen name without
- # listening to the `EditorPlugin.main_screen_changed` signal:
- # https://github.com/godotengine/godot-proposals/issues/2081
- EditorInterface.set_main_screen_editor("Script")
- EditorInterface.set_main_screen_editor("3D")
-
-func _on_main_screen_changed(screen_name: String) -> void:
- current_main_screen_name = screen_name
-
- # TODO: Bit of a hack to prevent pinned staying between view changes on the same scene.
- preview.unlink_camera()
- _on_editor_selection_changed()
-
-func _on_editor_selection_changed() -> void:
- if not is_main_screen_viewport():
- # This hides the preview "container" and not the preview itself, allowing
- # any locked previews to remain visible once switching back to 3D tab.
- preview.visible = false
- return
-
- preview.visible = true
-
- var selected_nodes = EditorInterface.get_selection().get_selected_nodes()
-
- var selected_camera_3d: Camera3D = find_camera_3d_or_null(selected_nodes)
- var selected_camera_2d: Camera2D = find_camera_2d_or_null(selected_nodes)
-
- if selected_camera_3d and current_main_screen_name == "3D":
- preview.link_with_camera_3d(selected_camera_3d)
- preview.request_show()
-
- elif selected_camera_2d and current_main_screen_name == "2D":
- preview.link_with_camera_2d(selected_camera_2d)
- preview.request_show()
-
- else:
- preview.request_hide()
-
-func is_main_screen_viewport() -> bool:
- return current_main_screen_name == "3D" or current_main_screen_name == "2D"
-
-func find_camera_3d_or_null(nodes: Array[Node]) -> Camera3D:
- var camera: Camera3D
-
- for node in nodes:
- if node is Camera3D:
- camera = node as Camera3D
- break
-
- return camera
-
-func find_camera_2d_or_null(nodes: Array[Node]) -> Camera2D:
- var camera: Camera2D
-
- for node in nodes:
- if node is Camera2D:
- camera = node as Camera2D
- break
-
- return camera
-
-func _on_selected_camera_3d_tree_exiting() -> void:
- preview.unlink_camera()
diff --git a/addons/anthonyec.camera_preview/preview.gd b/addons/anthonyec.camera_preview/preview.gd
deleted file mode 100644
index 3c07d04..0000000
--- a/addons/anthonyec.camera_preview/preview.gd
+++ /dev/null
@@ -1,404 +0,0 @@
-@tool
-
-class_name CameraPreview
-extends Control
-
-enum CameraType {
- CAMERA_2D,
- CAMERA_3D
-}
-
-enum PinnedPosition {
- LEFT,
- RIGHT,
-}
-
-enum InteractionState {
- NONE,
- RESIZE,
- DRAG,
-
- # Animation is split into 2 seperate states so that the tween is only
- # invoked once in the "start" state.
- START_ANIMATE_INTO_PLACE,
- ANIMATE_INTO_PLACE,
-}
-
-const margin_3d: Vector2 = Vector2(10, 10)
-const margin_2d: Vector2 = Vector2(20, 15)
-const panel_margin: float = 2
-const min_panel_size: float = 250
-
-@onready var panel: Panel = %Panel
-@onready var placeholder: Panel = %Placeholder
-@onready var preview_camera_3d: Camera3D = %Camera3D
-@onready var preview_camera_2d: Camera2D = %Camera2D
-@onready var sub_viewport: SubViewport = %SubViewport
-@onready var sub_viewport_text_rect: TextureRect = %TextureRect
-@onready var resize_left_handle: Button = %ResizeLeftHandle
-@onready var resize_right_handle: Button = %ResizeRightHandle
-@onready var lock_button: Button = %LockButton
-@onready var gradient: TextureRect = %Gradient
-@onready var viewport_margin_container: MarginContainer = %ViewportMarginContainer
-@onready var overlay_margin_container: MarginContainer = %OverlayMarginContainer
-@onready var overlay_container: Control = %OverlayContainer
-
-var camera_type: CameraType = CameraType.CAMERA_3D
-var pinned_position: PinnedPosition = PinnedPosition.RIGHT
-var viewport_ratio: float = 1
-var editor_scale: float = EditorInterface.get_editor_scale()
-var is_locked: bool
-var show_controls: bool
-var selected_camera_3d: Camera3D
-var selected_camera_2d: Camera2D
-
-var state: InteractionState = InteractionState.NONE
-var initial_mouse_position: Vector2
-var initial_panel_size: Vector2
-var initial_panel_position: Vector2
-
-func _ready() -> void:
- # Set initial width.
- panel.size.x = min_panel_size * editor_scale
-
- # Setting texture to viewport in code instead of directly in the editor
- # because otherwise an error "Path to node is invalid: Panel/SubViewport"
- # on first load. This is harmless but doesn't look great.
- #
- # This is a known issue:
- # https://github.com/godotengine/godot/issues/27790#issuecomment-499740220
- sub_viewport_text_rect.texture = sub_viewport.get_texture()
-
- # From what I can tell there's something wrong with how an editor theme
- # scales when used within a plugin. It seems to ignore the screen scale.
- # For instance, a 30x30px button will appear tiny on a retina display.
- #
- # Someone else had the issue with no luck:
- # https://forum.godotengine.org/t/how-to-scale-plugin-controls-to-look-the-same-in-4k-as-1080p/36151
- #
- # And seems Dialogic also scales buttons manually:
- # https://github.com/dialogic-godot/dialogic/blob/master/addons/dialogic/Editor/Common/sidebar.gd#L25C6-L38
- #
- # Maybe I don't know the correct way to do it, so for now the workaround is
- # to set the correct size in code using screen scale.
- var button_size = Vector2(30, 30) * editor_scale
- var margin_size: float = panel_margin * editor_scale
-
- resize_left_handle.size = button_size
- resize_left_handle.pivot_offset = Vector2(0, 0) * editor_scale
-
- resize_right_handle.size = button_size
- resize_right_handle.pivot_offset = Vector2(30, 30) * editor_scale
-
- lock_button.size = button_size
- lock_button.pivot_offset = Vector2(0, 30) * editor_scale
-
- viewport_margin_container.add_theme_constant_override("margin_left", margin_size)
- viewport_margin_container.add_theme_constant_override("margin_top", margin_size)
- viewport_margin_container.add_theme_constant_override("margin_right", margin_size)
- viewport_margin_container.add_theme_constant_override("margin_bottom", margin_size)
-
- overlay_margin_container.add_theme_constant_override("margin_left", margin_size)
- overlay_margin_container.add_theme_constant_override("margin_top", margin_size)
- overlay_margin_container.add_theme_constant_override("margin_right", margin_size)
- overlay_margin_container.add_theme_constant_override("margin_bottom", margin_size)
-
- # Parent node overlay size is not available on first ready, need to wait a
- # frame for it to be drawn.
- await get_tree().process_frame
-
- # Anchors are set in code because setting them in the editor UI doesn't take
- # editor scale into account.
- resize_left_handle.position = Vector2(0, 0)
- resize_right_handle.set_anchors_preset(Control.PRESET_TOP_LEFT)
-
- resize_right_handle.position = Vector2(overlay_container.size.x - button_size.x, 0)
- resize_right_handle.set_anchors_preset(Control.PRESET_TOP_RIGHT)
-
- lock_button.position = Vector2(0, overlay_container.size.y - button_size.y)
- lock_button.set_anchors_preset(Control.PRESET_BOTTOM_LEFT)
-
-func _process(_delta: float) -> void:
- if not visible: return
-
- match state:
- InteractionState.NONE:
- panel.size = get_clamped_size(panel.size)
- panel.position = get_pinned_position(pinned_position)
-
- InteractionState.RESIZE:
- var delta_mouse_position = initial_mouse_position - get_global_mouse_position()
- var resized_size = panel.size
-
- if pinned_position == PinnedPosition.LEFT:
- resized_size = initial_panel_size - delta_mouse_position
-
- if pinned_position == PinnedPosition.RIGHT:
- resized_size = initial_panel_size + delta_mouse_position
-
- panel.size = get_clamped_size(resized_size)
- panel.position = get_pinned_position(pinned_position)
-
- InteractionState.DRAG:
- placeholder.size = panel.size
-
- var global_mouse_position = get_global_mouse_position()
- var offset = initial_mouse_position - initial_panel_position
-
- panel.global_position = global_mouse_position - offset
-
- if global_mouse_position.x < global_position.x + size.x / 2:
- pinned_position = PinnedPosition.LEFT
- else:
- pinned_position = PinnedPosition.RIGHT
-
- placeholder.position = get_pinned_position(pinned_position)
-
- InteractionState.START_ANIMATE_INTO_PLACE:
- var final_position: Vector2 = get_pinned_position(pinned_position)
- var tween = get_tree().create_tween()
-
- tween.set_ease(Tween.EASE_OUT)
- tween.set_trans(Tween.TRANS_CUBIC)
- tween.tween_property(panel, "position", final_position, 0.3)
-
- tween.finished.connect(func():
- panel.position = final_position
- state = InteractionState.NONE
- )
-
- state = InteractionState.ANIMATE_INTO_PLACE
-
- # I couldn't get `mouse_entered` and `mouse_exited` events to work
- # nicely, so I use rect method instead. Plus using this method it's easy to
- # grow the hit area size.
- var panel_hover_rect = Rect2(panel.global_position, panel.size)
- panel_hover_rect = panel_hover_rect.grow(40)
-
- var mouse_position = get_global_mouse_position()
-
- show_controls = state != InteractionState.NONE or panel_hover_rect.has_point(mouse_position)
-
- # UI visibility.
- resize_left_handle.visible = show_controls and pinned_position == PinnedPosition.RIGHT
- resize_right_handle.visible = show_controls and pinned_position == PinnedPosition.LEFT
- lock_button.visible = show_controls or is_locked
- placeholder.visible = state == InteractionState.DRAG or state == InteractionState.ANIMATE_INTO_PLACE
- gradient.visible = show_controls
-
- # Sync camera settings.
- if camera_type == CameraType.CAMERA_3D and selected_camera_3d:
- sub_viewport.size = panel.size
-
- # Sync position and rotation without using a `RemoteTransform` node
- # because if you save a camera as a scene, the remote transform node will
- # be stored within the scene. Also it's harder to keep the remote
- # transform `remote_path` up-to-date with scene changes, which causes
- # many errors.
- preview_camera_3d.global_position = selected_camera_3d.global_position
- preview_camera_3d.global_rotation = selected_camera_3d.global_rotation
-
- preview_camera_3d.fov = selected_camera_3d.fov
- preview_camera_3d.projection = selected_camera_3d.projection
- preview_camera_3d.size = selected_camera_3d.size
- preview_camera_3d.cull_mask = selected_camera_3d.cull_mask
- preview_camera_3d.keep_aspect = selected_camera_3d.keep_aspect
- preview_camera_3d.near = selected_camera_3d.near
- preview_camera_3d.far = selected_camera_3d.far
- preview_camera_3d.h_offset = selected_camera_3d.h_offset
- preview_camera_3d.v_offset = selected_camera_3d.v_offset
- preview_camera_3d.attributes = selected_camera_3d.attributes
- preview_camera_3d.environment = selected_camera_3d.environment
-
- if camera_type == CameraType.CAMERA_2D and selected_camera_2d:
- var project_window_size = get_project_window_size()
- var ratio = project_window_size.x / panel.size.x
-
- # TODO: Is there a better way to fix this?
- # The camera border is visible sometimes due to pixel rounding.
- # Subtract 1px from right and bottom to hide this.
- var hide_camera_border_fix = Vector2(1, 1)
-
- sub_viewport.size = panel.size
- sub_viewport.size_2d_override = (panel.size - hide_camera_border_fix) * ratio
- sub_viewport.size_2d_override_stretch = true
-
- preview_camera_2d.global_position = selected_camera_2d.global_position
- preview_camera_2d.global_rotation = selected_camera_2d.global_rotation
-
- preview_camera_2d.offset = selected_camera_2d.offset
- preview_camera_2d.zoom = selected_camera_2d.zoom
- preview_camera_2d.ignore_rotation = selected_camera_2d.ignore_rotation
- preview_camera_2d.anchor_mode = selected_camera_2d.anchor_mode
- preview_camera_2d.limit_left = selected_camera_2d.limit_left
- preview_camera_2d.limit_right = selected_camera_2d.limit_right
- preview_camera_2d.limit_top = selected_camera_2d.limit_top
- preview_camera_2d.limit_bottom = selected_camera_2d.limit_bottom
-
-func link_with_camera_3d(camera_3d: Camera3D) -> void:
- # TODO: Camera may not be ready since this method is called in `_enter_tree`
- # in the plugin because of a workaround for:
- # https://github.com/godotengine/godot-proposals/issues/2081
- if not preview_camera_3d:
- return request_hide()
-
- var is_different_camera = camera_3d != preview_camera_3d
-
- # TODO: A bit messy.
- if is_different_camera:
- if preview_camera_3d.tree_exiting.is_connected(unlink_camera):
- preview_camera_3d.tree_exiting.disconnect(unlink_camera)
-
- if not camera_3d.tree_exiting.is_connected(unlink_camera):
- camera_3d.tree_exiting.connect(unlink_camera)
-
- sub_viewport.disable_3d = false
- sub_viewport.world_3d = camera_3d.get_world_3d()
-
- selected_camera_3d = camera_3d
- camera_type = CameraType.CAMERA_3D
-
-func link_with_camera_2d(camera_2d: Camera2D) -> void:
- if not preview_camera_2d:
- return request_hide()
-
- var is_different_camera = camera_2d != preview_camera_2d
-
- # TODO: A bit messy.
- if is_different_camera:
- if preview_camera_2d.tree_exiting.is_connected(unlink_camera):
- preview_camera_2d.tree_exiting.disconnect(unlink_camera)
-
- if not camera_2d.tree_exiting.is_connected(unlink_camera):
- camera_2d.tree_exiting.connect(unlink_camera)
-
- sub_viewport.disable_3d = true
- sub_viewport.world_2d = camera_2d.get_world_2d()
-
- selected_camera_2d = camera_2d
- camera_type = CameraType.CAMERA_2D
-
-func unlink_camera() -> void:
- if selected_camera_3d:
- selected_camera_3d = null
-
- if selected_camera_2d:
- selected_camera_2d = null
-
- is_locked = false
- lock_button.button_pressed = false
-
-func request_hide() -> void:
- if is_locked: return
- visible = false
-
-func request_show() -> void:
- visible = true
-
-func get_pinned_position(pinned_position: PinnedPosition) -> Vector2:
- var margin: Vector2 = margin_3d * editor_scale
-
- if camera_type == CameraType.CAMERA_2D:
- margin = margin_2d * editor_scale
-
- match pinned_position:
- PinnedPosition.LEFT:
- return Vector2.ZERO - Vector2(0, panel.size.y) - Vector2(-margin.x, margin.y)
- PinnedPosition.RIGHT:
- return size - panel.size - margin
- _:
- assert(false, "Unknown pinned position %s" % str(pinned_position))
-
- return Vector2.ZERO
-
-func get_clamped_size(desired_size: Vector2) -> Vector2:
- var viewport_ratio = get_project_window_ratio()
- var editor_viewport_size = get_editor_viewport_size()
-
- var max_bounds = Vector2(
- editor_viewport_size.x * 0.6,
- editor_viewport_size.y * 0.8
- )
-
- var clamped_size = desired_size
-
- # Apply aspect ratio.
- clamped_size = Vector2(clamped_size.x, clamped_size.x * viewport_ratio)
-
- # Clamp the max size while respecting the aspect ratio.
- if clamped_size.y >= max_bounds.y:
- clamped_size.x = max_bounds.y / viewport_ratio
- clamped_size.y = max_bounds.y
-
- if clamped_size.x >= max_bounds.x:
- clamped_size.x = max_bounds.x
- clamped_size.y = max_bounds.x * viewport_ratio
-
- # Clamp the min size based on if it's portrait or landscape. Portrait min
- # size should be based on it's height. Landscape min size is based on it's
- # width instead. Applying min width to a portrait size would make it too big.
- var is_portrait = viewport_ratio > 1
-
- if is_portrait and clamped_size.y <= min_panel_size * editor_scale:
- clamped_size.x = min_panel_size / viewport_ratio
- clamped_size.y = min_panel_size
- clamped_size = clamped_size * editor_scale
-
- if not is_portrait and clamped_size.x <= min_panel_size * editor_scale:
- clamped_size.x = min_panel_size
- clamped_size.y = min_panel_size * viewport_ratio
- clamped_size = clamped_size * editor_scale
-
- # Round down to avoid sub-pixel artifacts, mainly seen around the margins.
- return clamped_size.floor()
-
-func get_project_window_size() -> Vector2:
- var window_width = float(ProjectSettings.get_setting("display/window/size/viewport_width"))
- var window_height = float(ProjectSettings.get_setting("display/window/size/viewport_height"))
-
- return Vector2(window_width, window_height)
-
-func get_project_window_ratio() -> float:
- var project_window_size = get_project_window_size()
-
- return project_window_size.y / project_window_size.x
-
-func get_editor_viewport_size() -> Vector2:
- var fallback_size = EditorInterface.get_editor_main_screen().size
-
- # There isn't an API for getting the viewport node. Instead it has to be
- # found by checking the parent's parent of the subviewport and find
- # the correct node based on name and class.
- var editor_sub_viewport_3d = EditorInterface.get_editor_viewport_3d(0)
- var editor_viewport_container = editor_sub_viewport_3d.get_parent().get_parent().get_parent()
-
- # Early return incase editor tree structure has changed.
- if editor_viewport_container.get_class() != "Node3DEditorViewportContainer":
- return fallback_size
-
- return editor_viewport_container.size
-
-func _on_resize_handle_button_down() -> void:
- if state != InteractionState.NONE: return
-
- state = InteractionState.RESIZE
- initial_mouse_position = get_global_mouse_position()
- initial_panel_size = panel.size
-
-func _on_resize_handle_button_up() -> void:
- state = InteractionState.NONE
-
-func _on_drag_handle_button_down() -> void:
- if state != InteractionState.NONE: return
-
- state = InteractionState.DRAG
- initial_mouse_position = get_global_mouse_position()
- initial_panel_position = panel.global_position
-
-func _on_drag_handle_button_up() -> void:
- if state != InteractionState.DRAG: return
-
- state = InteractionState.START_ANIMATE_INTO_PLACE
-
-func _on_lock_button_pressed() -> void:
- is_locked = !is_locked
diff --git a/addons/anthonyec.camera_preview/preview.tscn b/addons/anthonyec.camera_preview/preview.tscn
deleted file mode 100644
index 77b3ced..0000000
--- a/addons/anthonyec.camera_preview/preview.tscn
+++ /dev/null
@@ -1,200 +0,0 @@
-[gd_scene load_steps=8 format=3 uid="uid://xybmfvufjuv"]
-
-[ext_resource type="Script" path="res://addons/anthonyec.camera_preview/preview.gd" id="1_6b32r"]
-[ext_resource type="Texture2D" uid="uid://do6d60od41vmg" path="res://addons/anthonyec.camera_preview/Pin.svg" id="2_p0pa8"]
-[ext_resource type="Texture2D" uid="uid://btc01wc11tiid" path="res://addons/anthonyec.camera_preview/GuiResizerTopLeft.svg" id="2_t64ej"]
-[ext_resource type="Texture2D" uid="uid://04l05jxuyt7k" path="res://addons/anthonyec.camera_preview/GuiResizerTopRight.svg" id="3_6yuab"]
-
-[sub_resource type="ViewportTexture" id="ViewportTexture_hchdq"]
-viewport_path = NodePath("Panel/SubViewport")
-
-[sub_resource type="Gradient" id="Gradient_11p6r"]
-offsets = PackedFloat32Array(0, 0.3, 0.6, 1)
-colors = PackedColorArray(0, 0, 0, 0.235294, 0, 0, 0, 0.0784314, 0, 0, 0, 0.0784314, 0, 0, 0, 0.235294)
-
-[sub_resource type="GradientTexture2D" id="GradientTexture2D_4dkve"]
-gradient = SubResource("Gradient_11p6r")
-width = 256
-height = 256
-fill_to = Vector2(2.08165e-12, 1)
-
-[node name="Preview" type="Control"]
-z_index = 999
-layout_mode = 3
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-script = ExtResource("1_6b32r")
-
-[node name="Placeholder" type="Panel" parent="."]
-unique_name_in_owner = true
-visible = false
-modulate = Color(1, 1, 1, 0.705882)
-layout_mode = 1
-anchors_preset = 3
-anchor_left = 1.0
-anchor_top = 1.0
-anchor_right = 1.0
-anchor_bottom = 1.0
-offset_left = -40.0
-offset_top = -40.0
-offset_right = 410.0
-offset_bottom = 410.0
-grow_horizontal = 0
-grow_vertical = 0
-
-[node name="Panel" type="Panel" parent="."]
-unique_name_in_owner = true
-clip_contents = true
-layout_mode = 1
-anchors_preset = 3
-anchor_left = 1.0
-anchor_top = 1.0
-anchor_right = 1.0
-anchor_bottom = 1.0
-offset_left = -520.0
-offset_top = -908.889
-offset_right = -20.0
-offset_bottom = -20.0
-grow_horizontal = 0
-grow_vertical = 0
-pivot_offset = Vector2(450, 300)
-
-[node name="SubViewport" type="SubViewport" parent="Panel"]
-unique_name_in_owner = true
-handle_input_locally = false
-gui_disable_input = true
-size_2d_override_stretch = true
-
-[node name="Camera3D" type="Camera3D" parent="Panel/SubViewport"]
-unique_name_in_owner = true
-current = true
-
-[node name="Camera2D" type="Camera2D" parent="Panel/SubViewport"]
-unique_name_in_owner = true
-ignore_rotation = false
-
-[node name="ViewportMarginContainer" type="MarginContainer" parent="Panel"]
-unique_name_in_owner = true
-clip_contents = true
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-mouse_filter = 2
-theme_override_constants/margin_left = 4
-theme_override_constants/margin_top = 4
-theme_override_constants/margin_right = 4
-theme_override_constants/margin_bottom = 4
-
-[node name="TextureRect" type="TextureRect" parent="Panel/ViewportMarginContainer"]
-unique_name_in_owner = true
-layout_mode = 2
-texture = SubResource("ViewportTexture_hchdq")
-expand_mode = 1
-
-[node name="Gradient" type="TextureRect" parent="Panel"]
-unique_name_in_owner = true
-visible = false
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-mouse_filter = 2
-texture = SubResource("GradientTexture2D_4dkve")
-
-[node name="OverlayMarginContainer" type="MarginContainer" parent="Panel"]
-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
-mouse_filter = 2
-theme_override_constants/margin_left = 4
-theme_override_constants/margin_top = 4
-theme_override_constants/margin_right = 4
-theme_override_constants/margin_bottom = 4
-
-[node name="OverlayContainer" type="Control" parent="Panel/OverlayMarginContainer"]
-unique_name_in_owner = true
-clip_contents = true
-layout_mode = 2
-mouse_filter = 2
-
-[node name="DragHandle" type="Button" parent="Panel/OverlayMarginContainer/OverlayContainer"]
-layout_mode = 1
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
-focus_mode = 0
-flat = true
-
-[node name="ResizeLeftHandle" type="Button" parent="Panel/OverlayMarginContainer/OverlayContainer"]
-unique_name_in_owner = true
-visible = false
-layout_mode = 1
-offset_right = 60.0
-offset_bottom = 60.0
-size_flags_horizontal = 0
-size_flags_vertical = 0
-mouse_default_cursor_shape = 12
-icon = ExtResource("2_t64ej")
-flat = true
-icon_alignment = 1
-expand_icon = true
-
-[node name="ResizeRightHandle" type="Button" parent="Panel/OverlayMarginContainer/OverlayContainer"]
-unique_name_in_owner = true
-visible = false
-layout_mode = 1
-anchors_preset = 1
-anchor_left = 1.0
-anchor_right = 1.0
-offset_left = -60.0
-offset_bottom = 60.0
-pivot_offset = Vector2(60, 60)
-size_flags_horizontal = 8
-size_flags_vertical = 0
-mouse_default_cursor_shape = 11
-icon = ExtResource("3_6yuab")
-flat = true
-icon_alignment = 1
-expand_icon = true
-
-[node name="LockButton" type="Button" parent="Panel/OverlayMarginContainer/OverlayContainer"]
-unique_name_in_owner = true
-visible = false
-layout_mode = 1
-anchors_preset = 2
-anchor_top = 1.0
-anchor_bottom = 1.0
-offset_top = -60.0
-offset_right = 60.0
-pivot_offset = Vector2(0, 60)
-size_flags_horizontal = 0
-size_flags_vertical = 8
-tooltip_text = "Always Show Preview"
-toggle_mode = true
-icon = ExtResource("2_p0pa8")
-flat = true
-icon_alignment = 1
-expand_icon = true
-
-[connection signal="button_down" from="Panel/OverlayMarginContainer/OverlayContainer/DragHandle" to="." method="_on_drag_handle_button_down"]
-[connection signal="button_up" from="Panel/OverlayMarginContainer/OverlayContainer/DragHandle" to="." method="_on_drag_handle_button_up"]
-[connection signal="renamed" from="Panel/OverlayMarginContainer/OverlayContainer/DragHandle" to="." method="_on_drag_handle_renamed"]
-[connection signal="button_down" from="Panel/OverlayMarginContainer/OverlayContainer/ResizeLeftHandle" to="." method="_on_resize_handle_button_down"]
-[connection signal="button_up" from="Panel/OverlayMarginContainer/OverlayContainer/ResizeLeftHandle" to="." method="_on_resize_handle_button_up"]
-[connection signal="button_down" from="Panel/OverlayMarginContainer/OverlayContainer/ResizeRightHandle" to="." method="_on_resize_handle_button_down"]
-[connection signal="button_up" from="Panel/OverlayMarginContainer/OverlayContainer/ResizeRightHandle" to="." method="_on_resize_handle_button_up"]
-[connection signal="pressed" from="Panel/OverlayMarginContainer/OverlayContainer/LockButton" to="." method="_on_lock_button_pressed"]
diff --git a/addons/discord-sdk-gd/Debug.svg b/addons/discord-sdk-gd/Debug.svg
new file mode 100644
index 0000000..7987166
--- /dev/null
+++ b/addons/discord-sdk-gd/Debug.svg
@@ -0,0 +1,10 @@
+
diff --git a/addons/anthonyec.camera_preview/Pin.svg.import b/addons/discord-sdk-gd/Debug.svg.import
similarity index 70%
rename from addons/anthonyec.camera_preview/Pin.svg.import
rename to addons/discord-sdk-gd/Debug.svg.import
index 27d274f..708694a 100644
--- a/addons/anthonyec.camera_preview/Pin.svg.import
+++ b/addons/discord-sdk-gd/Debug.svg.import
@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://do6d60od41vmg"
-path="res://.godot/imported/Pin.svg-83b09f5c00a829c5d8b136bf5bae65bc.ctex"
+uid="uid://ufh1hha1ehui"
+path="res://.godot/imported/Debug.svg-97b25f5d09dbf04212867cd1a46cf368.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://addons/anthonyec.camera_preview/Pin.svg"
-dest_files=["res://.godot/imported/Pin.svg-83b09f5c00a829c5d8b136bf5bae65bc.ctex"]
+source_file="res://addons/discord-sdk-gd/Debug.svg"
+dest_files=["res://.godot/imported/Debug.svg-97b25f5d09dbf04212867cd1a46cf368.ctex"]
[params]
@@ -32,6 +32,6 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-svg/scale=2.0
+svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
diff --git a/addons/discord-sdk-gd/Logo_V2_No_Bg.png b/addons/discord-sdk-gd/Logo_V2_No_Bg.png
new file mode 100644
index 0000000..fb6c700
Binary files /dev/null and b/addons/discord-sdk-gd/Logo_V2_No_Bg.png differ
diff --git a/addons/discord-sdk-gd/Logo_V2_No_Bg.png.import b/addons/discord-sdk-gd/Logo_V2_No_Bg.png.import
new file mode 100644
index 0000000..4d6ea22
--- /dev/null
+++ b/addons/discord-sdk-gd/Logo_V2_No_Bg.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://csl0e2px0cwc1"
+path="res://.godot/imported/Logo_V2_No_Bg.png-9c8178062d6891c8370df63a912bd8e2.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/discord-sdk-gd/Logo_V2_No_Bg.png"
+dest_files=["res://.godot/imported/Logo_V2_No_Bg.png-9c8178062d6891c8370df63a912bd8e2.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
diff --git a/addons/discord-sdk-gd/READ_ME_PLEASE.txt b/addons/discord-sdk-gd/READ_ME_PLEASE.txt
new file mode 100644
index 0000000..e070946
--- /dev/null
+++ b/addons/discord-sdk-gd/READ_ME_PLEASE.txt
@@ -0,0 +1,7 @@
+MINIMUM GODOT VERSION: 4.2
+
+PLEASE ACTIVATE THE PLUGIN UNDER Project -> Project Settings... -> Plugins -> DiscordSDK -> Status
+IGNORE THE RED ERRORS ON THE FIRST 2 RESTARTS
+READ THE TUTORIAL LINKED IN THE WINDOW THAT WILL OPEN ON PLUGIN ENABLE
+
+If nothing works, enable the plugin and delete /addons/discord-sdk-gd/bin/.gdignore
diff --git a/addons/discord-sdk-gd/bin/discord-rpc-gd.gdextension b/addons/discord-sdk-gd/bin/discord-rpc-gd.gdextension
new file mode 100644
index 0000000..a9416e3
--- /dev/null
+++ b/addons/discord-sdk-gd/bin/discord-rpc-gd.gdextension
@@ -0,0 +1,29 @@
+[configuration]
+
+entry_symbol = "discordsdkgd_library_init"
+compatibility_minimum = 4.1
+
+[libraries]
+
+macos.debug = "macos/libdiscord_game_sdk_binding_debug.dylib"
+macos.release = "macos/libdiscord_game_sdk_binding.dylib"
+windows.debug.x86_64 = "windows/discord_game_sdk_binding_debug.dll"
+windows.release.x86_64 = "windows/discord_game_sdk_binding.dll"
+linux.debug.x86_64 = "linux/libdiscord_game_sdk_binding_debug.so"
+linux.release.x86_64 = "linux/libdiscord_game_sdk_binding.so"
+linux.debug.arm64 = "linux/libdiscord_game_sdk_binding_debug.so"
+linux.release.arm64 = "linux/libdiscord_game_sdk_binding.so"
+linux.debug.rv64 = "linux/libdiscord_game_sdk_binding_debug.so"
+linux.release.rv64 = "linux/libdiscord_game_sdk_binding.so"
+
+[dependencies]
+
+macos = { "macos/libdiscord_game_sdk.dylib": "" }
+windows.debug.x86_64 = { "windows/discord_game_sdk.dll": "" }
+windows.release.x86_64 = { "windows/discord_game_sdk.dll": "" }
+linux.debug.x86_64 = { "linux/libdiscord_game_sdk.so": "" }
+linux.release.x86_64 = { "linux/libdiscord_game_sdk.so": "" }
+linux.debug.arm64 = { "linux/libdiscord_game_sdk.so": "" }
+linux.release.arm64 = { "linux/libdiscord_game_sdk.so": "" }
+linux.debug.rv64 = { "linux/libdiscord_game_sdk.so": "" }
+linux.release.rv64 = { "linux/libdiscord_game_sdk.so": "" }
diff --git a/addons/discord-sdk-gd/bin/linux/libdiscord_game_sdk.so b/addons/discord-sdk-gd/bin/linux/libdiscord_game_sdk.so
new file mode 100644
index 0000000..9dacf94
Binary files /dev/null and b/addons/discord-sdk-gd/bin/linux/libdiscord_game_sdk.so differ
diff --git a/addons/discord-sdk-gd/bin/linux/libdiscord_game_sdk_binding.so b/addons/discord-sdk-gd/bin/linux/libdiscord_game_sdk_binding.so
new file mode 100644
index 0000000..b11fce3
Binary files /dev/null and b/addons/discord-sdk-gd/bin/linux/libdiscord_game_sdk_binding.so differ
diff --git a/addons/discord-sdk-gd/bin/linux/libdiscord_game_sdk_binding_debug.so b/addons/discord-sdk-gd/bin/linux/libdiscord_game_sdk_binding_debug.so
new file mode 100644
index 0000000..aaaec56
Binary files /dev/null and b/addons/discord-sdk-gd/bin/linux/libdiscord_game_sdk_binding_debug.so differ
diff --git a/addons/discord-sdk-gd/bin/macos/libdiscord_game_sdk.dylib b/addons/discord-sdk-gd/bin/macos/libdiscord_game_sdk.dylib
new file mode 100644
index 0000000..2cc726d
Binary files /dev/null and b/addons/discord-sdk-gd/bin/macos/libdiscord_game_sdk.dylib differ
diff --git a/addons/discord-sdk-gd/bin/macos/libdiscord_game_sdk_binding.dylib b/addons/discord-sdk-gd/bin/macos/libdiscord_game_sdk_binding.dylib
new file mode 100644
index 0000000..97cf4af
Binary files /dev/null and b/addons/discord-sdk-gd/bin/macos/libdiscord_game_sdk_binding.dylib differ
diff --git a/addons/discord-sdk-gd/bin/macos/libdiscord_game_sdk_binding_debug.dylib b/addons/discord-sdk-gd/bin/macos/libdiscord_game_sdk_binding_debug.dylib
new file mode 100644
index 0000000..3e2c872
Binary files /dev/null and b/addons/discord-sdk-gd/bin/macos/libdiscord_game_sdk_binding_debug.dylib differ
diff --git a/addons/discord-sdk-gd/bin/windows/discord_game_sdk.dll b/addons/discord-sdk-gd/bin/windows/discord_game_sdk.dll
new file mode 100644
index 0000000..be946ea
Binary files /dev/null and b/addons/discord-sdk-gd/bin/windows/discord_game_sdk.dll differ
diff --git a/addons/discord-sdk-gd/bin/windows/discord_game_sdk_binding.dll b/addons/discord-sdk-gd/bin/windows/discord_game_sdk_binding.dll
new file mode 100644
index 0000000..c5688c7
Binary files /dev/null and b/addons/discord-sdk-gd/bin/windows/discord_game_sdk_binding.dll differ
diff --git a/addons/discord-sdk-gd/bin/windows/discord_game_sdk_binding_debug.dll b/addons/discord-sdk-gd/bin/windows/discord_game_sdk_binding_debug.dll
new file mode 100644
index 0000000..3e93cf0
Binary files /dev/null and b/addons/discord-sdk-gd/bin/windows/discord_game_sdk_binding_debug.dll differ
diff --git a/addons/discord-sdk-gd/bin/windows/discord_game_sdk_x86.dll b/addons/discord-sdk-gd/bin/windows/discord_game_sdk_x86.dll
new file mode 100644
index 0000000..45b9bb1
Binary files /dev/null and b/addons/discord-sdk-gd/bin/windows/discord_game_sdk_x86.dll differ
diff --git a/addons/discord-sdk-gd/example.gd b/addons/discord-sdk-gd/example.gd
new file mode 100644
index 0000000..9ee2184
--- /dev/null
+++ b/addons/discord-sdk-gd/example.gd
@@ -0,0 +1,38 @@
+class_name DiscordSDKTutorial
+extends Node
+
+## 1. Put the addons/ folder in your Godot project[br]
+## 2. Enable the addon in your Project Settings under "Plugins" and "DiscordSDK". [br](if it doesn't show up restart your project and try again)[br]
+## 3. Restart your project[br]
+## 4. Create an Application under https://discord.com/developers/applications and get the Application ID br]
+## 5. (optional) Set images under "Rich Presence" and "Art Assets" and remember the keys[br]
+##
+## This is your [code]_ready()[/code] function wich could be anywhere
+## [codeblock]
+## func _ready():
+## # Application ID
+## DiscordSDK.app_id = 1099618430065324082
+## # this is boolean if everything worked
+## print("Discord working: " + str(DiscordSDK.get_is_discord_working()))
+## # Set the first custom text row of the activity here
+## DiscordSDK.details = "A demo activity by vaporvee#1231"
+## # Set the second custom text row of the activity here
+## DiscordSDK.state = "Checkpoint 23/23"
+## # Image key for small image from "Art Assets" from the Discord Developer website
+## DiscordSDK.large_image = "game"
+## # Tooltip text for the large image
+## DiscordSDK.large_image_text = "Try it now!"
+## # Image key for large image from "Art Assets" from the Discord Developer website
+## DiscordSDK.small_image = "boss"
+## # Tooltip text for the small image
+## DiscordSDK.small_image_text = "Fighting the end boss! D:"
+## # "02:41 elapsed" timestamp for the activity
+## DiscordSDK.start_timestamp = int(Time.get_unix_time_from_system())
+## # "59:59 remaining" timestamp for the activity
+## DiscordSDK.end_timestamp = int(Time.get_unix_time_from_system()) + 3600
+## # Always refresh after changing the values!
+## DiscordSDK.refresh()
+## [/codeblock]
+##
+## @tutorial(More information here): https://github.com/vaporvee/discord-sdk-godot/wiki/Quick-start
+## @tutorial(Make your Application ID and else here): https://discord.com/developers/applications
diff --git a/addons/discord-sdk-gd/logo.png b/addons/discord-sdk-gd/logo.png
new file mode 100644
index 0000000..fb6c700
Binary files /dev/null and b/addons/discord-sdk-gd/logo.png differ
diff --git a/addons/discord-sdk-gd/logo.png.import b/addons/discord-sdk-gd/logo.png.import
new file mode 100644
index 0000000..a6947aa
--- /dev/null
+++ b/addons/discord-sdk-gd/logo.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://csl0e2px0cwc1"
+path="res://.godot/imported/logo.png-b59b4861dc0c64616d78af30082b08b5.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/discord-sdk-gd/logo.png"
+dest_files=["res://.godot/imported/logo.png-b59b4861dc0c64616d78af30082b08b5.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
diff --git a/addons/discord-sdk-gd/nodes/Debug.tscn b/addons/discord-sdk-gd/nodes/Debug.tscn
new file mode 100644
index 0000000..adf08fc
--- /dev/null
+++ b/addons/discord-sdk-gd/nodes/Debug.tscn
@@ -0,0 +1,267 @@
+[gd_scene load_steps=9 format=3 uid="uid://c1slhdnlsv2qt"]
+
+[ext_resource type="Texture2D" uid="uid://dnfq6kug4x6o2" path="res://addons/discord-sdk-gd/nodes/assets/Checked.svg" id="2_q6tao"]
+[ext_resource type="Texture2D" uid="uid://compmm3kviqqe" path="res://addons/discord-sdk-gd/nodes/assets/Unchecked.svg" id="3_5cyem"]
+[ext_resource type="Texture2D" uid="uid://dtc6ckladq0td" path="res://addons/discord-sdk-gd/nodes/assets/circle.svg" id="3_goflf"]
+
+[sub_resource type="GDScript" id="GDScript_ak1tp"]
+resource_name = "Debug"
+script/source = "extends Node
+
+func _ready():
+ DiscordSDK.connect(\"activity_join_request\",_on_activity_join_request)
+
+func _process(_delta):
+ if(DiscordSDK.get_is_discord_working()):
+ $Panel/TextureRect.self_modulate = Color(\"#3eff8d\")
+ $Panel/TextureRect/AnimationPlayer.play(\"pulsate\")
+ debug_text_update()
+ else:
+ $Panel/TextureRect.self_modulate = Color(\"#797979\")
+ $Panel/TextureRect/AnimationPlayer.stop()
+ debug_text_update()
+
+
+func debug_text_update():
+ $Panel/Info.text = \"Application ID : {id}
+Details: {details}
+State: {state}
+
+Large image key: {lkey}
+Large image text: {ltext}
+Small image key: {skey}
+Small image text: {stext}
+
+Start timestamp: {stimestamp}
+End timestamp: {etimestamp}
+
+Party ID: {partyid}
+Current party size: {cpartysize}
+Max party size: {mpartysize}
+Match secret: {msecret}
+Join secret: {jsecret}
+Spectate secret: {ssecret}
+Is party public: {ppublic} (needs to be activated in Discord client settings)
+
+Is instanced: {instanced}
+\"
+ $Panel/Info.text = $Panel/Info.text.replace(\"{ppublic}\",str(DiscordSDK.is_public_party)).replace(\"{instanced}\",str(DiscordSDK.instanced)).replace(\"{ssecret}\",DiscordSDK.spectate_secret).replace(\"{jsecret}\",DiscordSDK.join_secret).replace(\"{msecret}\",DiscordSDK.match_secret).replace(\"{mpartysize}\",str(DiscordSDK.max_party_size)).replace(\"{cpartysize}\",str(DiscordSDK.current_party_size)).replace(\"{partyid}\",DiscordSDK.party_id).replace(\"{id}\",str(DiscordSDK.app_id)).replace(\"{details}\",DiscordSDK.details).replace(\"{state}\",DiscordSDK.state).replace(\"{lkey}\",DiscordSDK.large_image).replace(\"{ltext}\",DiscordSDK.large_image_text).replace(\"{skey}\",DiscordSDK.small_image).replace(\"{stext}\",DiscordSDK.small_image_text).replace(\"{stimestamp}\",str(DiscordSDK.start_timestamp)).replace(\"{etimestamp}\",str(DiscordSDK.end_timestamp))
+
+var user_request = {};
+
+func _on_activity_join_request(user_requesting):
+ print(user_requesting)
+ user_request = user_requesting
+
+func _on_accept_join_request_pressed():
+ if(!user_request.is_empty()):
+ DiscordSDK.accept_join_request(user_request.id)
+
+func _on_invite_with_user_id_text_submitted(new_text):
+ DiscordSDK.send_invite(int(new_text),true,\"this is a test invite sent from godot\")
+
+func _on_accept_with_user_id_text_submitted(new_text):
+ DiscordSDK.accept_invite(int(new_text))
+
+func _on_print_current_user_on_console_pressed():
+ print(DiscordSDK.get_current_user())
+
+func _on_toggle_sdk_toggled(button_pressed):
+ if(button_pressed):
+ DiscordSDK.unclear()
+ else:
+ DiscordSDK.clear(false)
+
+func _on_print_friends_pressed():
+ print(DiscordSDK.get_all_relationships())
+"
+
+[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8abo6"]
+
+[sub_resource type="Animation" id="Animation_mmtmn"]
+length = 0.001
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:scale")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0.4),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector2(0.5, 0.5)]
+}
+
+[sub_resource type="Animation" id="Animation_5u02v"]
+resource_name = "pulsate"
+loop_mode = 1
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath(".:scale")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 0.5, 1),
+"transitions": PackedFloat32Array(1, 1, 1),
+"update": 0,
+"values": [Vector2(0.5, 0.5), Vector2(0.8, 0.8), Vector2(0.5, 0.5)]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_a7ofc"]
+_data = {
+"RESET": SubResource("Animation_mmtmn"),
+"pulsate": SubResource("Animation_5u02v")
+}
+
+[node name="DebugNodeGroup" type="Node"]
+editor_description = "This is a Debug Node wich will show (only if the project runs) some usefull info and buttons/input"
+script = SubResource("GDScript_ak1tp")
+
+[node name="Panel" type="Panel" parent="."]
+anchors_preset = -1
+anchor_right = 0.373
+anchor_bottom = 1.0
+offset_left = -5.0
+offset_right = 0.303955
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="Info" type="RichTextLabel" parent="Panel"]
+layout_mode = 0
+offset_left = 12.0
+offset_top = 21.0
+offset_right = 429.0
+offset_bottom = 461.0
+theme_override_font_sizes/normal_font_size = 14
+text = "Application ID : {id}
+Details: {details}
+State: {state}
+
+Large image key: {lkey}
+Large image text: {ltext}
+Small image key: {skey}
+Small image text: {stext}
+
+Start timestamp: {stimestamp}
+End timestamp: {etimestamp}
+
+Party ID: {partyid}
+Current party size: {cpartysize}
+Max party size: {mpartysize}
+Match secret: {msecret}
+Join secret: {jsecret}
+Spectate secret: {ssecret}
+Is party public: {ppublic} (needs to be activated in Discord client settings)
+
+Is instanced: {instanced}
+"
+fit_content = true
+
+[node name="PrintCurrentUserOnConsole" type="Button" parent="Panel"]
+layout_mode = 1
+anchors_preset = 4
+anchor_top = 0.5
+anchor_bottom = 0.5
+offset_left = 12.0
+offset_top = 138.375
+offset_right = 245.0
+offset_bottom = 171.375
+grow_vertical = 2
+text = "Print current user on console"
+
+[node name="PrintFriends" type="Button" parent="Panel"]
+layout_mode = 1
+anchors_preset = 4
+anchor_top = 0.5
+anchor_bottom = 0.5
+offset_left = 12.0
+offset_top = 176.5
+offset_right = 204.0
+offset_bottom = 207.5
+grow_vertical = 2
+text = "Print friends on console"
+
+[node name="AcceptJoinRequest" type="Button" parent="Panel"]
+layout_mode = 1
+anchors_preset = 4
+anchor_top = 0.5
+anchor_bottom = 0.5
+offset_left = 12.0
+offset_top = 212.875
+offset_right = 154.0
+offset_bottom = 243.875
+grow_vertical = 2
+text = "ACCEPT REQUEST"
+
+[node name="InviteWithUserID" type="LineEdit" parent="Panel"]
+layout_mode = 1
+anchors_preset = 4
+anchor_top = 0.5
+anchor_bottom = 0.5
+offset_left = 11.0
+offset_top = 250.375
+offset_right = 210.0
+offset_bottom = 281.375
+grow_vertical = 2
+size_flags_horizontal = 0
+placeholder_text = "Invite with user_id here"
+
+[node name="AcceptWithUserID" type="LineEdit" parent="Panel"]
+layout_mode = 1
+anchors_preset = 4
+anchor_top = 0.5
+anchor_bottom = 0.5
+offset_left = 11.0
+offset_top = 286.875
+offset_right = 260.0
+offset_bottom = 317.875
+grow_vertical = 2
+placeholder_text = "Accept Invite with user_id here"
+
+[node name="ToggleSDK" type="CheckButton" parent="Panel"]
+layout_mode = 1
+anchors_preset = 4
+anchor_top = 0.5
+anchor_bottom = 0.5
+offset_left = 298.0
+offset_top = 157.375
+offset_right = 1144.0
+offset_bottom = 665.375
+grow_vertical = 2
+scale = Vector2(0.05, 0.05)
+theme_override_icons/checked = ExtResource("2_q6tao")
+theme_override_icons/unchecked = ExtResource("3_5cyem")
+theme_override_styles/focus = SubResource("StyleBoxEmpty_8abo6")
+button_pressed = true
+
+[node name="TextureRect" type="TextureRect" parent="Panel"]
+self_modulate = Color(0.47451, 0.47451, 0.47451, 1)
+layout_mode = 1
+anchors_preset = -1
+anchor_left = 0.88
+anchor_top = 0.762
+anchor_right = 0.88
+anchor_bottom = 0.762
+offset_left = -28.8
+offset_top = -28.776
+offset_right = 28.0841
+offset_bottom = 28.1082
+grow_horizontal = 2
+grow_vertical = 2
+scale = Vector2(0.5, 0.5)
+pivot_offset = Vector2(29.0693, 29.0693)
+texture = ExtResource("3_goflf")
+
+[node name="AnimationPlayer" type="AnimationPlayer" parent="Panel/TextureRect"]
+libraries = {
+"": SubResource("AnimationLibrary_a7ofc")
+}
+
+[connection signal="pressed" from="Panel/PrintCurrentUserOnConsole" to="." method="_on_print_current_user_on_console_pressed"]
+[connection signal="pressed" from="Panel/PrintFriends" to="." method="_on_print_friends_pressed"]
+[connection signal="pressed" from="Panel/AcceptJoinRequest" to="." method="_on_accept_join_request_pressed"]
+[connection signal="text_submitted" from="Panel/InviteWithUserID" to="." method="_on_invite_with_user_id_text_submitted"]
+[connection signal="text_submitted" from="Panel/AcceptWithUserID" to="." method="_on_accept_with_user_id_text_submitted"]
+[connection signal="toggled" from="Panel/ToggleSDK" to="." method="_on_toggle_sdk_toggled"]
diff --git a/addons/discord-sdk-gd/nodes/assets/Checked.svg b/addons/discord-sdk-gd/nodes/assets/Checked.svg
new file mode 100644
index 0000000..d37a1c2
--- /dev/null
+++ b/addons/discord-sdk-gd/nodes/assets/Checked.svg
@@ -0,0 +1,18 @@
+
diff --git a/addons/anthonyec.camera_preview/GuiResizerTopLeft.svg.import b/addons/discord-sdk-gd/nodes/assets/Checked.svg.import
similarity index 67%
rename from addons/anthonyec.camera_preview/GuiResizerTopLeft.svg.import
rename to addons/discord-sdk-gd/nodes/assets/Checked.svg.import
index 9584d3b..bc9fc5a 100644
--- a/addons/anthonyec.camera_preview/GuiResizerTopLeft.svg.import
+++ b/addons/discord-sdk-gd/nodes/assets/Checked.svg.import
@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://btc01wc11tiid"
-path="res://.godot/imported/GuiResizerTopLeft.svg-eb563f557424c74239e878a1213a5bf4.ctex"
+uid="uid://dnfq6kug4x6o2"
+path="res://.godot/imported/Checked.svg-152467b95b56fa0b9944b5cc25700916.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://addons/anthonyec.camera_preview/GuiResizerTopLeft.svg"
-dest_files=["res://.godot/imported/GuiResizerTopLeft.svg-eb563f557424c74239e878a1213a5bf4.ctex"]
+source_file="res://addons/discord-sdk-gd/nodes/assets/Checked.svg"
+dest_files=["res://.godot/imported/Checked.svg-152467b95b56fa0b9944b5cc25700916.ctex"]
[params]
@@ -32,6 +32,6 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-svg/scale=2.0
+svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
diff --git a/addons/discord-sdk-gd/nodes/assets/Unchecked.svg b/addons/discord-sdk-gd/nodes/assets/Unchecked.svg
new file mode 100644
index 0000000..58cb234
--- /dev/null
+++ b/addons/discord-sdk-gd/nodes/assets/Unchecked.svg
@@ -0,0 +1,18 @@
+
diff --git a/addons/anthonyec.camera_preview/GuiResizerTopRight.svg.import b/addons/discord-sdk-gd/nodes/assets/Unchecked.svg.import
similarity index 67%
rename from addons/anthonyec.camera_preview/GuiResizerTopRight.svg.import
rename to addons/discord-sdk-gd/nodes/assets/Unchecked.svg.import
index 4a1fa5d..43b3409 100644
--- a/addons/anthonyec.camera_preview/GuiResizerTopRight.svg.import
+++ b/addons/discord-sdk-gd/nodes/assets/Unchecked.svg.import
@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://04l05jxuyt7k"
-path="res://.godot/imported/GuiResizerTopRight.svg-cc1dc8556d51357c5eb0b01d09d8f049.ctex"
+uid="uid://compmm3kviqqe"
+path="res://.godot/imported/Unchecked.svg-91cff67e13e7a1508fbc6a949f5f5f52.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://addons/anthonyec.camera_preview/GuiResizerTopRight.svg"
-dest_files=["res://.godot/imported/GuiResizerTopRight.svg-cc1dc8556d51357c5eb0b01d09d8f049.ctex"]
+source_file="res://addons/discord-sdk-gd/nodes/assets/Unchecked.svg"
+dest_files=["res://.godot/imported/Unchecked.svg-91cff67e13e7a1508fbc6a949f5f5f52.ctex"]
[params]
@@ -32,6 +32,6 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-svg/scale=2.0
+svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
diff --git a/addons/discord-sdk-gd/nodes/assets/circle.svg b/addons/discord-sdk-gd/nodes/assets/circle.svg
new file mode 100644
index 0000000..acd3753
--- /dev/null
+++ b/addons/discord-sdk-gd/nodes/assets/circle.svg
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/addons/discord-sdk-gd/nodes/assets/circle.svg.import b/addons/discord-sdk-gd/nodes/assets/circle.svg.import
new file mode 100644
index 0000000..d7598a8
--- /dev/null
+++ b/addons/discord-sdk-gd/nodes/assets/circle.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dtc6ckladq0td"
+path="res://.godot/imported/circle.svg-ca71b895eb1c5e7e6f2f2afe081d28dd.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/discord-sdk-gd/nodes/assets/circle.svg"
+dest_files=["res://.godot/imported/circle.svg-ca71b895eb1c5e7e6f2f2afe081d28dd.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
diff --git a/addons/discord-sdk-gd/nodes/debug.gd b/addons/discord-sdk-gd/nodes/debug.gd
new file mode 100644
index 0000000..a4e8ee0
--- /dev/null
+++ b/addons/discord-sdk-gd/nodes/debug.gd
@@ -0,0 +1,11 @@
+## This is a Debug Node wich will show some usefull info and buttons/input
+##
+## The DiscordSDK Debug Node will show info about the current values of its variables and some buttons to change them.
+##
+## @tutorial: https://github.com/vaporvee/discord-sdk-godot/wiki
+@tool
+extends Node
+
+func _ready() -> void:
+ const DebugNodeGroup: PackedScene = preload("res://addons/discord-sdk-gd/nodes/Debug.tscn")
+ add_child(DebugNodeGroup.instantiate())
diff --git a/addons/discord-sdk-gd/nodes/discord_autoload.gd b/addons/discord-sdk-gd/nodes/discord_autoload.gd
new file mode 100644
index 0000000..8cdeac2
--- /dev/null
+++ b/addons/discord-sdk-gd/nodes/discord_autoload.gd
@@ -0,0 +1,13 @@
+## This is a GDscript Node wich gets automatically added as Autoload while installing the addon.
+##
+## It can run in the background to comunicate with Discord.
+## You don't need to use it. If you remove it make sure to run [code]DiscordSDK.run_callbacks()[/code] in a [code]_process[/code] function.
+##
+## @tutorial: https://github.com/vaporvee/discord-sdk-godot/wiki
+extends Node
+
+func _ready() -> void:
+ pass
+
+func _process(_delta) -> void:
+ DiscordSDK.run_callbacks()
diff --git a/addons/discord-sdk-gd/plugin.cfg b/addons/discord-sdk-gd/plugin.cfg
new file mode 100644
index 0000000..4c72d16
--- /dev/null
+++ b/addons/discord-sdk-gd/plugin.cfg
@@ -0,0 +1,7 @@
+[plugin]
+
+name="DiscordSDK"
+description="Discord Game SDK support for GDScript in Godot"
+author="vaporvee"
+version="1.2.0"
+script="plugin.gd"
diff --git a/addons/discord-sdk-gd/plugin.gd b/addons/discord-sdk-gd/plugin.gd
new file mode 100644
index 0000000..f890de7
--- /dev/null
+++ b/addons/discord-sdk-gd/plugin.gd
@@ -0,0 +1,56 @@
+@tool
+extends EditorPlugin
+
+const DiscordSDKDebug = preload("res://addons/discord-sdk-gd/nodes/debug.gd")
+const DiscordSDKDebug_icon = preload("res://addons/discord-sdk-gd/Debug.svg")
+var loaded_DiscordSDKDebug = DiscordSDKDebug.new()
+var restart_window: ConfirmationDialog = preload("res://addons/discord-sdk-gd/restart_window.tscn").instantiate()
+var plugin_cfg: ConfigFile = ConfigFile.new()
+const plugin_data_filename = "/plugin_data.cfg"
+
+func _enter_tree() -> void:
+ add_custom_type("DiscordSDKDebug","Node",DiscordSDKDebug,DiscordSDKDebug_icon)
+ get_editor_interface().get_editor_settings().settings_changed.connect(_on_editor_settings_changed)
+
+func _ready() -> void:
+ await get_tree().create_timer(0.5).timeout
+ plugin_cfg.load(get_editor_interface().get_editor_paths().get_data_dir() + plugin_data_filename)
+ if !get_editor_interface().get_editor_settings().has_setting("DiscordSDK/EditorPresence/enabled"):
+ get_editor_interface().get_editor_settings().set_setting("DiscordSDK/EditorPresence/enabled",plugin_cfg.get_value("Discord","editor_presence",false))
+
+func _exit_tree():
+ if get_editor_interface().get_editor_settings().has_setting("DiscordSDK/EditorPresence/enabled"):
+ get_editor_interface().get_editor_settings().erase("DiscordSDK/EditorPresence/enabled")
+
+func _enable_plugin() -> void:
+ if FileAccess.file_exists(ProjectSettings.globalize_path("res://") + "addons/discord-sdk-gd/bin/.gdignore"):
+ DirAccess.remove_absolute(ProjectSettings.globalize_path("res://") + "addons/discord-sdk-gd/bin/.gdignore")
+ add_autoload_singleton("DiscordSDKLoader","res://addons/discord-sdk-gd/nodes/discord_autoload.gd")
+ restart_window.connect("confirmed", save_no_restart)
+ restart_window.connect("canceled", save_and_restart)
+ get_editor_interface().popup_dialog_centered(restart_window)
+ print("IGNORE RED ERROR MESSAGES BEFORE THE SECOND RESTART!")
+
+func _disable_plugin() -> void:
+ remove_autoload_singleton("DiscordSDKLoader")
+ FileAccess.open("res://addons/discord-sdk-gd/bin/.gdignore",FileAccess.WRITE)
+ remove_custom_type("DiscordSDKDebug")
+ get_editor_interface().get_editor_settings().erase("DiscordSDK/EditorPresence/enabled")
+ push_warning("Please restart the editor to fully disable the DiscordSDK plugin")
+
+func save_and_restart() -> void:
+ get_editor_interface().restart_editor(true)
+
+func save_no_restart() -> void:
+ get_editor_interface().restart_editor(false)
+
+var editor_presence: Node
+func _on_editor_settings_changed() -> void:
+ plugin_cfg.set_value("Discord","editor_presence",get_editor_interface().get_editor_settings().get_setting("DiscordSDK/EditorPresence/enabled"))
+ plugin_cfg.save(get_editor_interface().get_editor_paths().get_data_dir() + plugin_data_filename)
+ if ClassDB.class_exists("EditorPresence") && editor_presence == null:
+ editor_presence = ClassDB.instantiate("EditorPresence")
+ if get_editor_interface().get_editor_settings().has_setting("DiscordSDK/EditorPresence/enabled") && get_editor_interface().get_editor_settings().get_setting("DiscordSDK/EditorPresence/enabled"):
+ add_child(editor_presence)
+ else:
+ editor_presence.queue_free()
diff --git a/addons/discord-sdk-gd/restart_window.tscn b/addons/discord-sdk-gd/restart_window.tscn
new file mode 100644
index 0000000..0559c3e
--- /dev/null
+++ b/addons/discord-sdk-gd/restart_window.tscn
@@ -0,0 +1,112 @@
+[gd_scene load_steps=8 format=3 uid="uid://byc4c6d5tpomq"]
+
+[ext_resource type="Texture2D" uid="uid://csl0e2px0cwc1" path="res://addons/discord-sdk-gd/Logo_V2_No_Bg.png" id="1_0svbg"]
+
+[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_1t7mm"]
+
+[sub_resource type="Theme" id="Theme_swwco"]
+Button/styles/focus = SubResource("StyleBoxEmpty_1t7mm")
+
+[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_5vqdt"]
+
+[sub_resource type="Image" id="Image_v4whe"]
+data = {
+"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 227, 227, 227, 36, 224, 224, 224, 168, 224, 224, 224, 233, 224, 224, 224, 236, 224, 224, 224, 170, 231, 231, 231, 31, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 227, 227, 227, 36, 224, 224, 224, 234, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 239, 230, 230, 230, 30, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 168, 224, 224, 224, 255, 224, 224, 224, 186, 224, 224, 224, 32, 224, 224, 224, 33, 224, 224, 224, 187, 224, 224, 224, 255, 225, 225, 225, 167, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 237, 224, 224, 224, 255, 224, 224, 224, 33, 255, 255, 255, 0, 255, 255, 255, 0, 227, 227, 227, 36, 224, 224, 224, 255, 224, 224, 224, 234, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 237, 224, 224, 224, 255, 224, 224, 224, 33, 255, 255, 255, 0, 255, 255, 255, 0, 229, 229, 229, 38, 224, 224, 224, 255, 224, 224, 224, 229, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 164, 224, 224, 224, 255, 224, 224, 224, 187, 225, 225, 225, 34, 227, 227, 227, 36, 224, 224, 224, 192, 224, 224, 224, 255, 224, 224, 224, 162, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 24, 225, 225, 225, 215, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 229, 224, 224, 224, 32, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 24, 224, 224, 224, 216, 224, 224, 224, 255, 224, 224, 224, 210, 224, 224, 224, 161, 224, 224, 224, 232, 224, 224, 224, 231, 225, 225, 225, 159, 230, 230, 230, 30, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 107, 224, 224, 224, 255, 224, 224, 224, 210, 230, 230, 230, 20, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 105, 230, 230, 230, 20, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 221, 224, 224, 224, 130, 255, 255, 255, 1, 255, 255, 255, 1, 225, 225, 225, 134, 224, 224, 224, 224, 225, 225, 225, 223, 224, 224, 224, 132, 255, 255, 255, 1, 255, 255, 255, 6, 224, 224, 224, 137, 224, 224, 224, 231, 224, 224, 224, 255, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 130, 225, 225, 225, 133, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 129, 224, 224, 224, 137, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 65, 224, 224, 224, 255, 224, 224, 224, 220, 225, 225, 225, 223, 224, 224, 224, 255, 226, 226, 226, 61, 224, 224, 224, 65, 224, 224, 224, 255, 224, 224, 224, 222, 224, 224, 224, 231, 224, 224, 224, 255, 227, 227, 227, 62, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 225, 225, 225, 67, 224, 224, 224, 255, 224, 224, 224, 219, 224, 224, 224, 222, 224, 224, 224, 255, 227, 227, 227, 63, 225, 225, 225, 67, 224, 224, 224, 255, 224, 224, 224, 219, 224, 224, 224, 230, 224, 224, 224, 255, 227, 227, 227, 63, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 225, 225, 225, 127, 224, 224, 224, 129, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 225, 225, 225, 126, 225, 225, 225, 135, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 221, 225, 225, 225, 127, 255, 255, 255, 0, 255, 255, 255, 1, 224, 224, 224, 128, 224, 224, 224, 220, 224, 224, 224, 219, 225, 225, 225, 127, 255, 255, 255, 0, 255, 255, 255, 5, 225, 225, 225, 134, 224, 224, 224, 229, 224, 224, 224, 255, 255, 255, 255, 0),
+"format": "RGBA8",
+"height": 16,
+"mipmaps": false,
+"width": 16
+}
+
+[sub_resource type="ImageTexture" id="ImageTexture_gdtpn"]
+image = SubResource("Image_v4whe")
+
+[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_7v0rg"]
+
+[node name="RestartWindow" type="ConfirmationDialog"]
+title = "Restart required"
+initial_position = 2
+size = Vector2i(430, 500)
+visible = true
+transient = false
+unresizable = true
+theme = SubResource("Theme_swwco")
+ok_button_text = "Restart"
+cancel_button_text = "Save and restart"
+
+[node name="Panel" type="Panel" parent="."]
+anchors_preset = 5
+anchor_left = 0.5
+anchor_right = 0.5
+offset_left = -207.0
+offset_top = 8.0
+offset_right = 207.0
+offset_bottom = 451.0
+grow_horizontal = 2
+mouse_filter = 1
+
+[node name="VBoxContainer" type="VBoxContainer" parent="Panel"]
+custom_minimum_size = Vector2(400, 0)
+layout_mode = 1
+anchors_preset = 5
+anchor_left = 0.5
+anchor_right = 0.5
+offset_left = -200.0
+offset_right = 200.0
+offset_bottom = 389.0
+grow_horizontal = 2
+
+[node name="HSeparator" type="HSeparator" parent="Panel/VBoxContainer"]
+layout_mode = 2
+mouse_filter = 1
+theme_override_constants/separation = 15
+theme_override_styles/separator = SubResource("StyleBoxEmpty_5vqdt")
+
+[node name="HBoxContainer" type="HBoxContainer" parent="Panel/VBoxContainer"]
+layout_mode = 2
+size_flags_horizontal = 4
+size_flags_vertical = 4
+theme_override_constants/separation = 10
+
+[node name="DocsIcon" type="TextureRect" parent="Panel/VBoxContainer/HBoxContainer"]
+layout_mode = 2
+size_flags_horizontal = 8
+size_flags_vertical = 4
+texture = SubResource("ImageTexture_gdtpn")
+stretch_mode = 2
+
+[node name="LinkButton" type="LinkButton" parent="Panel/VBoxContainer/HBoxContainer"]
+layout_mode = 2
+size_flags_horizontal = 4
+size_flags_vertical = 8
+mouse_default_cursor_shape = 16
+theme_override_font_sizes/font_size = 20
+text = "HOW TO USE"
+uri = "https://vaporvee.com/docs/discord-sdk-godot#quick-start"
+
+[node name="TextureRect" type="TextureRect" parent="Panel/VBoxContainer"]
+custom_minimum_size = Vector2(128, 128)
+layout_mode = 2
+size_flags_horizontal = 4
+size_flags_vertical = 0
+texture = ExtResource("1_0svbg")
+expand_mode = 1
+
+[node name="RichTextLabel" type="RichTextLabel" parent="Panel/VBoxContainer"]
+custom_minimum_size = Vector2(400, 250)
+layout_mode = 2
+size_flags_horizontal = 4
+size_flags_vertical = 0
+mouse_filter = 1
+theme_override_font_sizes/normal_font_size = 16
+theme_override_styles/normal = SubResource("StyleBoxEmpty_7v0rg")
+bbcode_enabled = true
+text = "[center]Thanks for enabling the
+[rainbow]Discord Game SDK Plugin[/rainbow]
+made by vaporvee. ❤️
+
+
+You need to [wave]restart[/wave] the editor to fully enable this plugin!
+Do you want to [wave]save[/wave] your project before restarting?
+
+Error messages after the first two restarts are normal. Please ignore them!"
diff --git a/project.godot b/project.godot
index c1906e2..1263c4f 100644
--- a/project.godot
+++ b/project.godot
@@ -25,6 +25,7 @@ LuaSingleton="*res://Scripts/lua_singleton.gd"
Fs="*res://Scripts/fs.gd"
Music="*res://Scripts/music.gd"
CommentsData="*res://Scripts/comments_data.gd"
+DiscordSDKLoader="*res://addons/discord-sdk-gd/nodes/discord_autoload.gd"
[display]
@@ -33,6 +34,10 @@ window/size/viewport_height=1080
window/stretch/mode="canvas_items"
window/stretch/aspect="ignore"
+[editor_plugins]
+
+enabled=PackedStringArray("res://addons/discord-sdk-gd/plugin.cfg")
+
[gui]
theme/custom_font="res://Fonts/FiraCode-Regular.ttf"