continued making autoload and more obsolete

This commit is contained in:
2023-11-30 22:41:45 +01:00
parent dba8569ebc
commit 6fd58b0ddf
26 changed files with 575 additions and 21 deletions

View File

@@ -6,7 +6,8 @@
"${default}", "${default}",
"${workspaceFolder}/src/lib/godot-cpp/gen/include", "${workspaceFolder}/src/lib/godot-cpp/gen/include",
"${workspaceFolder}/src/lib/godot-cpp/include", "${workspaceFolder}/src/lib/godot-cpp/include",
"${workspaceFolder}/src/lib/godot-cpp/gdextension" "${workspaceFolder}/src/lib/godot-cpp/gdextension",
"${workspaceFolder}/src/lib/godot-cpp/gen/include"
], ],
"defines": [ "defines": [
"_DEBUG", "_DEBUG",

View File

@@ -1,7 +1,7 @@
[configuration] [configuration]
entry_symbol = "discordsdkgd_library_init" entry_symbol = "discordsdkgd_library_init"
compatibility_minimum = 4.1 compatibility_minimum = 4.2
[libraries] [libraries]

View File

@@ -20,6 +20,7 @@ func _process(_delta):
$Panel/TextureRect.self_modulate = Color(\"#797979\") $Panel/TextureRect.self_modulate = Color(\"#797979\")
$Panel/TextureRect/AnimationPlayer.stop() $Panel/TextureRect/AnimationPlayer.stop()
debug_text_update() debug_text_update()
func debug_text_update(): func debug_text_update():
$Panel/Info.text = \"Application ID : {id} $Panel/Info.text = \"Application ID : {id}

View File

@@ -7,32 +7,22 @@ var loaded_DiscordSDKDebug = DiscordSDKDebug.new()
var restart_window: Control = preload("res://addons/discord-sdk-gd/restart_window.tscn").instantiate() var restart_window: Control = preload("res://addons/discord-sdk-gd/restart_window.tscn").instantiate()
func _enter_tree() -> void: func _enter_tree() -> void:
add_custom_type("DiscordSDKDebug","Node",DiscordSDKDebug,DiscordSDKDebug_icon) add_custom_type("DiscordSDKDebug","Node",DiscordSDKDebug,DiscordSDKDebug_icon)
add_autoload_singleton("DiscordSDKLoader", "res://addons/discord-sdk-gd/nodes/core_updater.gd")
ProjectSettings.set_setting("DiscordSDK/EditorPresence/enabled",false) ProjectSettings.set_setting("DiscordSDK/EditorPresence/enabled",false)
ProjectSettings.set_as_basic("DiscordSDK/EditorPresence/enabled",true) ProjectSettings.set_as_basic("DiscordSDK/EditorPresence/enabled",true)
ProjectSettings.set_initial_value("DiscordSDK/EditorPresence/enabled",false) ProjectSettings.set_initial_value("DiscordSDK/EditorPresence/enabled",false)
get_node("/root/").add_child(DiscordLoader.new())
func _enable_plugin() -> void: func _enable_plugin() -> void:
if FileAccess.file_exists(ProjectSettings.globalize_path("res://") + "addons/discord-sdk-gd/bin/.gdignore"): 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") DirAccess.remove_absolute(ProjectSettings.globalize_path("res://") + "addons/discord-sdk-gd/bin/.gdignore")
if FileAccess.file_exists(ProjectSettings.globalize_path("res://") + "addons/discord-sdk-gd/nodes/.gdignore"): if FileAccess.file_exists(ProjectSettings.globalize_path("res://") + "addons/discord-sdk-gd/nodes/.gdignore"):
DirAccess.remove_absolute(ProjectSettings.globalize_path("res://") + "addons/discord-sdk-gd/nodes/.gdignore") DirAccess.remove_absolute(ProjectSettings.globalize_path("res://") + "addons/discord-sdk-gd/nodes/.gdignore")
add_control_to_container(EditorPlugin.CONTAINER_TOOLBAR,restart_window)
restart_window.get_child(0).connect("canceled",save_restart)
restart_window.get_child(0).connect("confirmed",restart)
func _disable_plugin() -> void: func _disable_plugin() -> void:
FileAccess.open("res://addons/discord-sdk-gd/bin/.gdignore",FileAccess.WRITE) FileAccess.open("res://addons/discord-sdk-gd/bin/.gdignore",FileAccess.WRITE)
FileAccess.open("res://addons/discord-sdk-gd/nodes/.gdignore",FileAccess.WRITE) FileAccess.open("res://addons/discord-sdk-gd/nodes/.gdignore",FileAccess.WRITE)
push_warning("DiscordSDK Addon got disabled. PLEASE RESTART THE EDITOR!")
remove_autoload_singleton("DiscordSDKLoader")
remove_custom_type("DiscordSDKDebug") remove_custom_type("DiscordSDKDebug")
ProjectSettings.clear("DiscordSDK/EditorPresence/enabled") ProjectSettings.clear("DiscordSDK/EditorPresence/enabled")
func save_restart() -> void:
get_editor_interface().restart_editor(true)
func restart() -> void:
get_editor_interface().restart_editor(false)

View File

@@ -0,0 +1,11 @@
Editor debugger for Godot Engine
--------------------------------
Copyright (c) 2018 Marc Gilleron
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,393 @@
@tool
extends Control
const Util = preload("util.gd")
signal node_selected(node)
@onready var _popup_menu : PopupMenu = get_node("PopupMenu")
@onready var _inspection_checkbox : CheckBox = get_node("VBoxContainer/ShowInInspectorCheckbox")
@onready var _label : Label = get_node("VBoxContainer/Label")
@onready var _tree_view : Tree = get_node("VBoxContainer/Tree")
@onready var _save_branch_file_dialog : FileDialog = get_node("SaveBranchFileDialog")
const METADATA_NODE_NAME = 0
enum POPUP_ACTIONS {
SAVE_BRANCH_AS_SCENE,
COPY_PATH_TO_CLIPBOARD,
COPY_NODE_TYPES_TO_CLIPBOARD,
}
const _popup_action_names = {
POPUP_ACTIONS.SAVE_BRANCH_AS_SCENE: {
"title": "Save branch as scene",
"tooltip": "Save the branch as a new scene in a directory of your choice"
},
POPUP_ACTIONS.COPY_PATH_TO_CLIPBOARD: {
"title": "Copy path to clipboard",
"tooltip": "Copy the path to the node in the format \"/path/to/node\""
},
POPUP_ACTIONS.COPY_NODE_TYPES_TO_CLIPBOARD:{
"title": "Copy typed path to clipboard",
"tooltip": "Copy the path to the node in the format [[\"type\", \"node\"], [\"type\", \"node\"], ...]"
},
}
const _update_interval = 1.0
var _time_before_next_update := 0.0
var _control_highlighter: ColorRect = null
# The default "icon not found" texture. Captured so it can be compared against when trying to
# find a specific icon.
# @see _update_node_view
var _no_texture := get_theme_icon("", "EditorIcons")
func get_tree_view() -> Tree:
return _tree_view
func _ready() -> void:
_popup_menu.clear()
for id in _popup_action_names:
_popup_menu.add_item(_popup_action_names[id].title, id)
var index := _popup_menu.get_item_index(id)
_popup_menu.set_item_tooltip(index, _popup_action_names[id].tooltip)
func _enter_tree() -> void:
if Util.is_in_edited_scene(self):
return
_control_highlighter = ColorRect.new()
_control_highlighter.color = Color(1, 1, 0, 0.2)
_control_highlighter.mouse_filter = Control.MOUSE_FILTER_IGNORE
_control_highlighter.hide()
get_viewport().call_deferred("add_child", _control_highlighter)
func _exit_tree() -> void:
if _control_highlighter != null:
_control_highlighter.queue_free()
func _process(delta: float) -> void:
if Util.is_in_edited_scene(self):
set_process(false)
return
var viewport := get_viewport()
_label.text = str(viewport.get_mouse_position())
_time_before_next_update -= delta
if _time_before_next_update <= 0:
_time_before_next_update = _update_interval
_update_tree()
func _update_tree() -> void:
var root := get_tree().root
if root == null:
_tree_view.clear()
return
#print("Updating tree")
var root_view := _tree_view.get_root()
if root_view == null:
root_view = _create_node_view(root, null)
_update_branch(root, root_view)
func _update_branch(root: Node, root_view: TreeItem) -> void:
if root_view.collapsed and root_view.get_first_child() != null:
# Don't care about collapsed nodes.
# The editor is a big tree, don't waste cycles on things you can't see
#print(root, " is collapsed and first child is ", root_view.get_first_child())
return
var children_views := root_view.get_children()
for i in root.get_child_count(true):
var child := root.get_child(i, true)
var child_view: TreeItem
if i >= len(children_views):
child_view = _create_node_view(child, root_view)
children_views.append(child_view)
else:
child_view = children_views[i]
var child_view_name: String = child_view.get_metadata(METADATA_NODE_NAME)
if child.name != child_view_name:
_update_node_view(child, child_view)
_update_branch(child, child_view)
# Remove excess tree items
if root.get_child_count(true) < len(children_views):
for i in range(root.get_child_count(true), len(children_views)):
children_views[i].free()
func _create_node_view(node: Node, parent_view: TreeItem) -> TreeItem:
#print("Create view for ", node)
assert(node is Node)
assert(parent_view == null or parent_view is TreeItem)
var view := _tree_view.create_item(parent_view)
view.collapsed = true
_update_node_view(node, view)
return view
func _update_node_view(node: Node, view: TreeItem) -> void:
assert(node is Node)
assert(view is TreeItem)
var icon_texture := get_theme_icon(node.get_class(), "EditorIcons")
if (icon_texture == null or icon_texture == _no_texture):
icon_texture = get_theme_icon("Node", "EditorIcons")
view.set_icon(0, icon_texture)
view.set_text(0, str(node.get_class(), ": ", node.name))
view.set_metadata(METADATA_NODE_NAME, node.name)
func _select_node() -> void:
var node_view := _tree_view.get_selected()
var node := _get_node_from_view(node_view)
print("Selected ", node)
_highlight_node(node)
emit_signal("node_selected", node)
func _on_Tree_item_selected() -> void:
_select_node()
func _on_Tree_item_mouse_selected(position: Vector2, mouse_button_index: int) -> void:
if mouse_button_index == MOUSE_BUTTON_RIGHT:
_select_node()
_popup_menu.popup()
_popup_menu.set_position(get_viewport().get_mouse_position())
func _highlight_node(node: Node) -> void:
if node is Control:
var target_control := (node as Control)
_control_highlighter.global_position = target_control.global_position
_control_highlighter.size = target_control.size
_control_highlighter.show()
else:
_control_highlighter.hide()
func _get_node_from_view(node_view: TreeItem) -> Node:
if node_view.get_parent() == null:
return get_tree().root
# Reconstruct path
var path: String = node_view.get_metadata(METADATA_NODE_NAME)
var parent_view := node_view
while parent_view.get_parent() != null:
parent_view = parent_view.get_parent()
# Exclude root
if parent_view.get_parent() == null:
break
path = str(parent_view.get_metadata(METADATA_NODE_NAME), "/", path)
var node := get_tree().root.get_node(path)
return node
func _focus_in_tree(node: Node) -> void:
_update_tree()
var parent: Node = get_tree().root
var path := node.get_path()
var parent_view := _tree_view.get_root()
var node_view: TreeItem = null
for i in range(1, path.get_name_count()):
var part := path.get_name(i)
print(part)
var child_view := parent_view.get_first_child()
if child_view == null:
_update_branch(parent, parent_view)
child_view = parent_view.get_first_child()
while child_view != null and child_view.get_metadata(METADATA_NODE_NAME) != part:
child_view = child_view.get_next()
if child_view == null:
node_view = parent_view
break
node_view = child_view
parent = parent.get_node(NodePath(part))
parent_view = child_view
if node_view != null:
_uncollapse_to_root(node_view)
node_view.select(0)
_tree_view.ensure_cursor_is_visible()
static func _uncollapse_to_root(node_view: TreeItem) -> void:
var parent_view := node_view.get_parent()
while parent_view != null:
parent_view.collapsed = false
parent_view = parent_view.get_parent()
static func _get_index_path(node: Node) -> Array[int]:
var ipath: Array[int] = []
while node.get_parent() != null:
ipath.append(node.get_index())
node = node.get_parent()
ipath.reverse()
return ipath
func _on_Tree_nothing_selected() -> void:
_control_highlighter.hide()
func _input(event: InputEvent) -> void:
if event is InputEventKey:
if event.pressed:
if event.keycode == KEY_F12:
pick(get_viewport().get_mouse_position())
func pick(mpos: Vector2) -> void:
var root := get_tree().root
var node := _pick(root, mpos)
if node != null:
print("Picked ", node, " at ", node.get_path())
_focus_in_tree(node)
else:
_highlight_node(null)
func is_inspection_enabled() -> bool:
return _inspection_checkbox.button_pressed
func _pick(root: Node, mpos: Vector2, level := 0) -> Node:
# var s := ""
# for i in level:
# s = str(s, " ")
#
# print(s, "Looking at ", root, ": ", root.name)
var node: Node = null
for i in root.get_child_count(true):
var child := root.get_child(i, true)
if (child is CanvasItem and not child.visible):
#print(s, child, " is invisible or viewport")
continue
if child is Viewport:
continue
if child == _control_highlighter:
continue
if child is Control and child.get_global_rect().has_point(mpos):
var c := _pick(child, mpos, level + 1)
if c != null:
return c
else:
node = child
else:
var c := _pick(child, mpos, level + 1)
if c != null:
return c
return node
# @param root
# @param {Dictionary[Node, Node]} owners
static func override_ownership(root: Node, owners: Dictionary, include_internal: bool) -> void:
assert(root is Node)
_override_ownership_recursive(root, root, owners, include_internal)
# @param root
# @param node
# @param {Dictionary[Node, Node]} owners
static func _override_ownership_recursive(root: Node, node: Node, owners: Dictionary,
include_internal: bool) -> void:
# Make root own all children of node.
for child in node.get_children(include_internal):
if child.owner != null:
owners[child] = child.owner
child.set_owner(root)
_override_ownership_recursive(root, child, owners, include_internal)
# @param root
# @param {Dictionary[Node, Node]} owners
static func restore_ownership(root: Node, owners: Dictionary, include_internal: bool) -> void:
assert(root is Node)
# Remove all of root's children's owners.
# Also restore node ownership to nodes which had their owner overridden.
for child in root.get_children(include_internal):
if owners.has(child):
child.owner = owners[child]
owners.erase(child)
else:
child.set_owner(null)
restore_ownership(child, owners, include_internal)
func _on_ShowInInspectorCheckbox_toggled(_button_pressed: bool) -> void:
pass
func _on_popup_menu_id_pressed(id: int) -> void:
_popup_menu.hide()
match id:
POPUP_ACTIONS.SAVE_BRANCH_AS_SCENE:
_save_branch_file_dialog.popup_centered_ratio()
POPUP_ACTIONS.COPY_PATH_TO_CLIPBOARD:
var node_view := _tree_view.get_selected()
var node := _get_node_from_view(node_view)
DisplayServer.clipboard_set(node.get_path())
print("Copied to clipboard: %s"%[node.get_path()])
POPUP_ACTIONS.COPY_NODE_TYPES_TO_CLIPBOARD:
var node_view := _tree_view.get_selected()
var node := _get_node_from_view(node_view)
var node_types := []
while node.get_parent():
var tuple := PackedStringArray([node.get_class(), node.name])
node_types.append(tuple)
node = node.get_parent()
node_types.reverse()
var node_types_str := "%s"%[node_types]
DisplayServer.clipboard_set(node_types_str)
print("Copied to clipboard: %s"%[node_types_str])
func _on_SaveBranchFileDialog_file_selected(path: String) -> void:
var node_view := _tree_view.get_selected()
var node := _get_node_from_view(node_view)
# Make the selected node own all it's children.
var owners := {}
override_ownership(node, owners, true)
# Pack the selected node and it's children into a scene then save it.
var packed_scene := PackedScene.new()
packed_scene.pack(node)
ResourceSaver.save(packed_scene, path)
# Revert ownership of all children.
restore_ownership(node, owners, true)

View File

@@ -0,0 +1,42 @@
[gd_scene load_steps=2 format=3 uid="uid://d0sxhc6l66egc"]
[ext_resource type="Script" path="res://addons/zylann.editor_debugger/dock.gd" id="1"]
[node name="EditorDebugger" type="Control"]
layout_mode = 3
anchors_preset = 0
offset_right = 238.0
offset_bottom = 347.0
script = ExtResource("1")
[node name="PopupMenu" type="PopupMenu" parent="."]
hide_on_item_selection = false
hide_on_checkable_item_selection = false
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
[node name="ShowInInspectorCheckbox" type="CheckBox" parent="VBoxContainer"]
layout_mode = 2
text = "Show in inspector"
[node name="Tree" type="Tree" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
allow_rmb_select = true
[node name="Label" type="Label" parent="VBoxContainer"]
layout_mode = 2
text = "Hello World"
[node name="SaveBranchFileDialog" type="FileDialog" parent="."]
filters = PackedStringArray("*.tscn ; TSCN", "*.scn ; SCN", "*.res ; RES")
[connection signal="id_pressed" from="PopupMenu" to="." method="_on_popup_menu_id_pressed"]
[connection signal="toggled" from="VBoxContainer/ShowInInspectorCheckbox" to="." method="_on_ShowInInspectorCheckbox_toggled"]
[connection signal="item_mouse_selected" from="VBoxContainer/Tree" to="." method="_on_Tree_item_mouse_selected"]
[connection signal="item_selected" from="VBoxContainer/Tree" to="." method="_on_Tree_item_selected"]
[connection signal="nothing_selected" from="VBoxContainer/Tree" to="." method="_on_Tree_nothing_selected"]
[connection signal="file_selected" from="SaveBranchFileDialog" to="." method="_on_SaveBranchFileDialog_file_selected"]

View File

@@ -0,0 +1,8 @@
[plugin]
name="Editor debugger"
description="Tools to inspect the editor, within the editor"
author="Marc Gilleron"
version="0.3"
script="plugin.gd"

View File

@@ -0,0 +1,28 @@
@tool
extends EditorPlugin
const DockScene = preload("dock.tscn")
const Dock = preload("dock.gd")
var _dock: Dock = null
func _enter_tree() -> void:
_dock = DockScene.instantiate()
_dock.node_selected.connect(_on_EditorDebugger_node_selected)
add_control_to_dock(DOCK_SLOT_RIGHT_UL, _dock)
#var editor_settings := get_editor_interface().get_editor_settings()
func _exit_tree() -> void:
remove_control_from_docks(_dock)
_dock.free()
_dock = null
func _on_EditorDebugger_node_selected(node: Node) -> void:
if _dock.is_inspection_enabled():
# Oops.
get_editor_interface().inspect_object(node)

View File

@@ -0,0 +1,33 @@
@tool
static func get_node_in_parents(node: Node, klass) -> Node:
while node != null:
node = node.get_parent()
if node != null and is_instance_of(node, klass):
return node
return null
static func is_in_edited_scene(node: Node) -> bool:
# .___.
# /) ,-^ ^-.
# // / \
# .-------| |--------------/ __ __ \-------------------.__
# |WMWMWMW| |>>>>>>>>>>>>> | />>\ />>\ |>>>>>>>>>>>>>>>>>>>>>>:>
# `-------| |--------------| \__/ \__/ |-------------------'^^
# \\ \ /|\ /
# \) \ \_/ /
# | |
# |+H+H+H+|
# \ /
# ^-----^
# TODO https://github.com/godotengine/godot/issues/17592
# This may break some day, don't fly planes with this bullshit.
# Obviously it won't work for nested viewports since that's basically what this function checks.
if not node.is_inside_tree():
return false
var vp := get_node_in_parents(node, Viewport)
if vp == null:
return false
return vp.get_parent() != null

View File

@@ -19,10 +19,6 @@ boot_splash/image="res://assets/Banner_v1.png"
boot_splash/fullsize=false boot_splash/fullsize=false
config/icon="res://assets/Logo_V2.png" config/icon="res://assets/Logo_V2.png"
[autoload]
DiscordSDKLoader="*res://addons/discord-sdk-gd/nodes/core_updater.gd"
[display] [display]
window/size/resizable=false window/size/resizable=false
@@ -33,7 +29,7 @@ project/assembly_name="GDExtension Test Project"
[editor_plugins] [editor_plugins]
enabled=PackedStringArray("res://addons/discord-sdk-gd/plugin.cfg") enabled=PackedStringArray("res://addons/discord-sdk-gd/plugin.cfg", "res://addons/zylann.editor_debugger/plugin.cfg")
[filesystem] [filesystem]

View File

@@ -1,9 +1,7 @@
#include "discordgodot.h" #include "discordgodot.h"
#include "lib/discord_game_sdk/cpp/discord.h" #include "lib/discord_game_sdk/cpp/discord.h"
#include <godot_cpp/core/class_db.hpp> #include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/classes/editor_plugin.hpp>
#include <godot_cpp/variant/utility_functions.hpp> #include <godot_cpp/variant/utility_functions.hpp>
#include <godot_cpp/classes/time.hpp>
#define BIND_METHOD(method, ...) godot::ClassDB::bind_method(D_METHOD(#method, __VA_ARGS__), &discord_sdk::method) #define BIND_METHOD(method, ...) godot::ClassDB::bind_method(D_METHOD(#method, __VA_ARGS__), &discord_sdk::method)
#define BIND_SET_GET(property_name, variant_type) \ #define BIND_SET_GET(property_name, variant_type) \

26
src/loader_node.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include "loader_node.h"
#include "discordgodot.h"
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
using namespace godot;
#define EDITOR_PRESENCE_ID 1108142249990176808
void DiscordLoader::_bind_methods()
{
}
DiscordLoader::DiscordLoader()
{
}
DiscordLoader::~DiscordLoader()
{
}
void DiscordLoader::_process(double delta)
{
discord_sdk *singleton = discord_sdk::get_singleton();
singleton->coreupdate();
}

25
src/loader_node.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef LOADER_NODE_H
#define LOADER_NODE_H
#include <godot_cpp/classes/node.hpp>
namespace godot
{
class DiscordLoader : public Node
{
GDCLASS(DiscordLoader, Node)
protected:
static void _bind_methods();
public:
DiscordLoader();
~DiscordLoader();
void _process(double delta) override;
};
}
#endif

View File

@@ -7,6 +7,7 @@
#include <godot_cpp/godot.hpp> #include <godot_cpp/godot.hpp>
#include "discordgodot.h" #include "discordgodot.h"
#include "loader_node.h"
using namespace godot; using namespace godot;
static discord_sdk *discordsdk; static discord_sdk *discordsdk;
@@ -19,6 +20,7 @@ void initialize_discordsdk_module(ModuleInitializationLevel p_level)
discordsdk = memnew(discord_sdk); discordsdk = memnew(discord_sdk);
Engine::get_singleton()->register_singleton("discord_sdk", discord_sdk::get_singleton()); Engine::get_singleton()->register_singleton("discord_sdk", discord_sdk::get_singleton());
} }
ClassDB::register_class<DiscordLoader>();
} }
void uninitialize_discordsdk_module(ModuleInitializationLevel p_level) void uninitialize_discordsdk_module(ModuleInitializationLevel p_level)