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"