feat: updated engine
This commit is contained in:
parent
cbe99774ff
commit
f4cf6b3999
6607 changed files with 910135 additions and 430025 deletions
|
|
@ -30,11 +30,12 @@
|
|||
|
||||
#include "debug_adapter_parser.h"
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/os/os.h"
|
||||
#include "editor/debugger/debug_adapter/debug_adapter_protocol.h"
|
||||
#include "editor/debugger/editor_debugger_node.h"
|
||||
#include "editor/debugger/script_editor_debugger.h"
|
||||
#include "editor/export/editor_export.h"
|
||||
#include "editor/export/editor_export_platform.h"
|
||||
#include "editor/run/editor_run_bar.h"
|
||||
#include "editor/script/script_editor_plugin.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@
|
|||
#include "core/debugger/debugger_marshalls.h"
|
||||
#include "core/io/json.h"
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/os/os.h"
|
||||
#include "editor/debugger/debug_adapter/debug_adapter_parser.h"
|
||||
#include "editor/debugger/script_editor_debugger.h"
|
||||
#include "editor/editor_log.h"
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#include "core/io/stream_peer_tcp.h"
|
||||
#include "core/io/tcp_server.h"
|
||||
#include "editor/debugger/debug_adapter/debug_adapter_types.h"
|
||||
#include "scene/debugger/scene_debugger.h"
|
||||
#include "scene/debugger/scene_debugger_object.h"
|
||||
|
||||
#define DAP_MAX_BUFFER_SIZE 4194304 // 4MB
|
||||
#define DAP_MAX_CLIENTS 8
|
||||
|
|
|
|||
|
|
@ -80,11 +80,14 @@ void DebugAdapterServer::_notification(int p_what) {
|
|||
|
||||
void DebugAdapterServer::start() {
|
||||
remote_port = (DebugAdapterServer::port_override > -1) ? DebugAdapterServer::port_override : (int)_EDITOR_GET("network/debug_adapter/remote_port");
|
||||
if (protocol.start(remote_port, IPAddress("127.0.0.1")) == OK) {
|
||||
EditorNode::get_log()->add_message("--- Debug adapter server started on port " + itos(remote_port) + " ---", EditorLog::MSG_TYPE_EDITOR);
|
||||
set_process_internal(true);
|
||||
started = true;
|
||||
const Error status = protocol.start(remote_port, IPAddress("127.0.0.1"));
|
||||
if (status != OK) {
|
||||
EditorNode::get_log()->add_message("--- Failed to start Debug adapter server on port " + itos(remote_port) + ": " + error_names[status] + " ---", EditorLog::MSG_TYPE_EDITOR);
|
||||
return;
|
||||
}
|
||||
EditorNode::get_log()->add_message("--- Debug adapter server started on port " + itos(remote_port) + " ---", EditorLog::MSG_TYPE_EDITOR);
|
||||
set_process_internal(true);
|
||||
started = true;
|
||||
}
|
||||
|
||||
void DebugAdapterServer::stop() {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "debugger_editor_plugin.h"
|
||||
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/os/keyboard.h"
|
||||
#include "editor/debugger/editor_debugger_node.h"
|
||||
#include "editor/debugger/editor_debugger_server.h"
|
||||
|
|
@ -38,7 +39,6 @@
|
|||
#include "editor/editor_node.h"
|
||||
#include "editor/run/run_instances_dialog.h"
|
||||
#include "editor/script/script_editor_plugin.h"
|
||||
#include "editor/settings/editor_command_palette.h"
|
||||
#include "editor/settings/editor_settings.h"
|
||||
#include "scene/gui/popup_menu.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ private:
|
|||
|
||||
public:
|
||||
virtual String get_plugin_name() const override { return "Debugger"; }
|
||||
bool has_main_screen() const override { return false; }
|
||||
|
||||
DebuggerEditorPlugin(PopupMenu *p_menu);
|
||||
~DebuggerEditorPlugin();
|
||||
|
|
|
|||
|
|
@ -32,10 +32,14 @@
|
|||
|
||||
#include "core/debugger/debugger_marshalls.h"
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/variant/typed_dictionary.h"
|
||||
#include "editor/docks/inspector_dock.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_undo_redo_manager.h"
|
||||
#include "scene/debugger/scene_debugger.h"
|
||||
#include "scene/debugger/scene_debugger_object.h"
|
||||
|
||||
bool EditorDebuggerRemoteObjects::_set(const StringName &p_name, const Variant &p_value) {
|
||||
return _set_impl(p_name, p_value, "");
|
||||
|
|
@ -47,7 +51,7 @@ bool EditorDebuggerRemoteObjects::_set_impl(const StringName &p_name, const Vari
|
|||
return false;
|
||||
}
|
||||
|
||||
// Change it back to the real name when fetching.
|
||||
// Change it back to the real name when sending it.
|
||||
if (name == "Script") {
|
||||
name = "script";
|
||||
} else if (name.begins_with("Metadata/")) {
|
||||
|
|
@ -72,18 +76,10 @@ bool EditorDebuggerRemoteObjects::_set_impl(const StringName &p_name, const Vari
|
|||
}
|
||||
|
||||
bool EditorDebuggerRemoteObjects::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
String name = p_name;
|
||||
if (!prop_values.has(name)) {
|
||||
if (!prop_values.has(p_name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change it back to the real name when fetching.
|
||||
if (name == "Script") {
|
||||
name = "script";
|
||||
} else if (name.begins_with("Metadata/")) {
|
||||
name = name.replace_first("Metadata/", "metadata/");
|
||||
}
|
||||
|
||||
r_ret = prop_values[p_name][remote_object_ids[0]];
|
||||
return true;
|
||||
}
|
||||
|
|
@ -108,7 +104,13 @@ void EditorDebuggerRemoteObjects::set_property_field(const StringName &p_propert
|
|||
String EditorDebuggerRemoteObjects::get_title() {
|
||||
if (!remote_object_ids.is_empty() && ObjectID(remote_object_ids[0].operator uint64_t()).is_valid()) {
|
||||
const int size = remote_object_ids.size();
|
||||
return size == 1 ? vformat(TTR("Remote %s: %d"), type_name, remote_object_ids[0]) : vformat(TTR("Remote %s (%d Selected)"), type_name, size);
|
||||
if (size == 1) {
|
||||
if (node_name.is_empty() || node_name == type_name) {
|
||||
return vformat(TTR("Remote %s: %d"), type_name, remote_object_ids[0]);
|
||||
}
|
||||
return vformat(TTR("Remote %s (%s): %d"), type_name, node_name, remote_object_ids[0]);
|
||||
}
|
||||
return vformat(TTR("Remote %s (%d Selected)"), type_name, size);
|
||||
}
|
||||
|
||||
return "<null>";
|
||||
|
|
@ -120,12 +122,17 @@ Variant EditorDebuggerRemoteObjects::get_variant(const StringName &p_name) {
|
|||
return var;
|
||||
}
|
||||
|
||||
void EditorDebuggerRemoteObjects::clear() {
|
||||
prop_list.clear();
|
||||
prop_values.clear();
|
||||
}
|
||||
|
||||
void EditorDebuggerRemoteObjects::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_title"), &EditorDebuggerRemoteObjects::get_title);
|
||||
ClassDB::bind_method("_hide_script_from_inspector", &EditorDebuggerRemoteObjects::_hide_script_from_inspector);
|
||||
ClassDB::bind_method("_hide_metadata_from_inspector", &EditorDebuggerRemoteObjects::_hide_metadata_from_inspector);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("values_edited", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::DICTIONARY, "values", PROPERTY_HINT_DICTIONARY_TYPE, "uint64_t:Variant"), PropertyInfo(Variant::STRING, "field")));
|
||||
ADD_SIGNAL(MethodInfo("values_edited", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::DICTIONARY, "values", PROPERTY_HINT_DICTIONARY_TYPE, "uint64_t;Variant"), PropertyInfo(Variant::STRING, "field")));
|
||||
}
|
||||
|
||||
/// EditorDebuggerInspector
|
||||
|
|
@ -200,34 +207,6 @@ EditorDebuggerRemoteObjects *EditorDebuggerInspector::set_objects(const Array &p
|
|||
remote_objects_list.push_back(remote_objects);
|
||||
}
|
||||
|
||||
StringName class_name = objects[0].class_name;
|
||||
if (class_name != SNAME("Object")) {
|
||||
// Search for the common class between all selected objects.
|
||||
bool check_type_again = true;
|
||||
while (check_type_again) {
|
||||
check_type_again = false;
|
||||
|
||||
if (class_name == SNAME("Object") || class_name == StringName()) {
|
||||
// All objects inherit from Object, so no need to continue checking.
|
||||
class_name = SNAME("Object");
|
||||
break;
|
||||
}
|
||||
|
||||
// Check that all objects inherit from type_name.
|
||||
for (const SceneDebuggerObject &obj : objects) {
|
||||
if (obj.class_name == class_name || ClassDB::is_parent_class(obj.class_name, class_name)) {
|
||||
continue; // class_name is the same or a parent of the object's class.
|
||||
}
|
||||
|
||||
// class_name is not a parent of the node's class, so check again with the parent class.
|
||||
class_name = ClassDB::get_parent_class(class_name);
|
||||
check_type_again = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
remote_objects->type_name = class_name;
|
||||
|
||||
// Search for properties that are present in all selected objects.
|
||||
struct UsageData {
|
||||
int qty = 0;
|
||||
|
|
@ -254,8 +233,27 @@ EditorDebuggerRemoteObjects *EditorDebuggerInspector::set_objects(const Array &p
|
|||
usage[pinfo.name] = usage_dt;
|
||||
}
|
||||
|
||||
// Make sure only properties with the same exact PropertyInfo data will appear.
|
||||
if (usage[pinfo.name].prop.first == pinfo) {
|
||||
// Make sure only properties with matching PropertyInfo data will appear.
|
||||
if (usage[pinfo.name].prop.first.name == pinfo.name &&
|
||||
usage[pinfo.name].prop.first.type == pinfo.type &&
|
||||
usage[pinfo.name].prop.first.class_name == pinfo.class_name &&
|
||||
usage[pinfo.name].prop.first.hint == pinfo.hint &&
|
||||
usage[pinfo.name].prop.first.hint_string == pinfo.hint_string) {
|
||||
if (usage[pinfo.name].prop.first.usage != pinfo.usage) {
|
||||
// Checkable properties (mostly theme items) need special treatment.
|
||||
if (usage[pinfo.name].prop.first.usage & PROPERTY_USAGE_CHECKABLE && pinfo.usage & PROPERTY_USAGE_CHECKABLE) {
|
||||
if (usage[pinfo.name].prop.first.usage & PROPERTY_USAGE_CHECKED) {
|
||||
pinfo.usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
|
||||
} else {
|
||||
pinfo.usage &= ~(PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED);
|
||||
}
|
||||
|
||||
if (usage[pinfo.name].prop.first.usage != pinfo.usage) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usage[pinfo.name].qty++;
|
||||
usage[pinfo.name].values[obj.id] = prop.second;
|
||||
}
|
||||
|
|
@ -311,6 +309,79 @@ EditorDebuggerRemoteObjects *EditorDebuggerInspector::set_objects(const Array &p
|
|||
remote_objects->prop_values[pinfo.name] = KV.value.values;
|
||||
}
|
||||
|
||||
StringName class_name = objects[0].class_name;
|
||||
bool has_custom_class = true;
|
||||
|
||||
if (usage.has("Script")) {
|
||||
// Check if all objects have the same script.
|
||||
Ref<Script> common_scr;
|
||||
LocalVector<Variant> keys = usage["Script"].values.get_key_list();
|
||||
for (const Variant &key : keys) {
|
||||
Ref<Script> scr = usage["Script"].values[key];
|
||||
if (scr.is_null()) {
|
||||
has_custom_class = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (common_scr.is_null()) {
|
||||
common_scr = scr;
|
||||
} else if (scr != common_scr) {
|
||||
has_custom_class = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_custom_class) {
|
||||
// Now check if the script has a custom class.
|
||||
if (common_scr.is_null()) {
|
||||
has_custom_class = false;
|
||||
} else {
|
||||
const StringName scr_class = common_scr->get_global_name();
|
||||
if (scr_class.is_empty()) {
|
||||
has_custom_class = false;
|
||||
} else {
|
||||
class_name = scr_class;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_custom_class && class_name != SNAME("Object")) {
|
||||
// Search for the common class between all selected objects.
|
||||
bool check_type_again = true;
|
||||
while (check_type_again) {
|
||||
check_type_again = false;
|
||||
|
||||
if (class_name.is_empty() || class_name == SNAME("Object")) {
|
||||
// All objects inherit from Object, so no need to continue checking.
|
||||
class_name = SNAME("Object");
|
||||
break;
|
||||
}
|
||||
|
||||
// Check that all objects inherit from type_name.
|
||||
for (const SceneDebuggerObject &obj : objects) {
|
||||
if (obj.class_name == class_name || ClassDB::is_parent_class(obj.class_name, class_name)) {
|
||||
continue; // class_name is the same or a parent of the object's class.
|
||||
}
|
||||
|
||||
// class_name is not a parent of the node's class, so check again with the parent class.
|
||||
class_name = ClassDB::get_parent_class(class_name);
|
||||
check_type_again = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
remote_objects->type_name = class_name;
|
||||
remote_objects->node_name = "";
|
||||
if (objects.size() == 1) {
|
||||
for (const SceneDebuggerObject::SceneDebuggerProperty &prop : objects[0].properties) {
|
||||
if (prop.first.name == "name") {
|
||||
remote_objects->node_name = prop.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (old_prop_size == remote_objects->prop_list.size() && new_props_added == 0) {
|
||||
// Only some may have changed, if so, then update those, if they exist.
|
||||
for (const String &E : changed) {
|
||||
|
|
@ -374,8 +445,14 @@ void EditorDebuggerInspector::add_stack_variable(const Array &p_array, int p_off
|
|||
if (var.var_type == Variant::OBJECT && v) {
|
||||
v = Object::cast_to<EncodedObjectAsID>(v)->get_object_id();
|
||||
h = PROPERTY_HINT_OBJECT_ID;
|
||||
hs = "Object";
|
||||
hs = var.type_hint;
|
||||
|
||||
// Makes the call stack select the node in the remote tree. See https://github.com/godotengine/godot/issues/79477
|
||||
if (n == "self") {
|
||||
_object_selected(v);
|
||||
}
|
||||
}
|
||||
|
||||
String type;
|
||||
switch (var.type) {
|
||||
case 0:
|
||||
|
|
@ -427,7 +504,7 @@ void EditorDebuggerInspector::clear_stack_variables() {
|
|||
|
||||
String EditorDebuggerInspector::get_stack_variable(const String &p_var) {
|
||||
for (KeyValue<StringName, TypedDictionary<uint64_t, Variant>> &E : variables->prop_values) {
|
||||
String v = E.key.operator String();
|
||||
String v = E.key.string();
|
||||
if (v.get_slicec('/', 1) == p_var) {
|
||||
return variables->get_variant(v);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,11 +30,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "core/variant/typed_dictionary.h"
|
||||
#include "editor/inspector/editor_inspector.h"
|
||||
|
||||
class SceneDebuggerObject;
|
||||
|
||||
template <typename K, typename V>
|
||||
class TypedDictionary;
|
||||
|
||||
class EditorDebuggerRemoteObjects : public Object {
|
||||
GDCLASS(EditorDebuggerRemoteObjects, Object);
|
||||
|
||||
|
|
@ -50,6 +52,7 @@ protected:
|
|||
public:
|
||||
TypedArray<uint64_t> remote_object_ids;
|
||||
String type_name;
|
||||
String node_name; // For human-readable name.
|
||||
List<PropertyInfo> prop_list;
|
||||
HashMap<StringName, TypedDictionary<uint64_t, Variant>> prop_values;
|
||||
|
||||
|
|
@ -60,10 +63,7 @@ public:
|
|||
String get_title();
|
||||
Variant get_variant(const StringName &p_name);
|
||||
|
||||
void clear() {
|
||||
prop_list.clear();
|
||||
prop_values.clear();
|
||||
}
|
||||
void clear();
|
||||
|
||||
void update() { notify_property_list_changed(); }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@
|
|||
|
||||
#include "editor_debugger_node.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/undo_redo.h"
|
||||
#include "editor/debugger/editor_debugger_plugin.h"
|
||||
#include "editor/debugger/editor_debugger_tree.h"
|
||||
|
|
@ -49,6 +53,7 @@
|
|||
#include "scene/gui/menu_button.h"
|
||||
#include "scene/gui/tab_container.h"
|
||||
#include "scene/resources/packed_scene.h"
|
||||
#include "servers/display/display_server.h"
|
||||
|
||||
template <typename Func>
|
||||
void _for_all(TabContainer *p_node, const Func &p_func) {
|
||||
|
|
@ -67,9 +72,7 @@ EditorDebuggerNode::EditorDebuggerNode() {
|
|||
set_layout_key("Debugger");
|
||||
set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_debugger_bottom_panel", TTRC("Toggle Debugger Dock"), KeyModifierMask::ALT | Key::D));
|
||||
set_default_slot(EditorDock::DOCK_SLOT_BOTTOM);
|
||||
set_available_layouts(EditorDock::DOCK_LAYOUT_HORIZONTAL);
|
||||
set_global(false);
|
||||
set_transient(true);
|
||||
set_available_layouts(EditorDock::DOCK_LAYOUT_HORIZONTAL | EditorDock::DOCK_LAYOUT_FLOATING);
|
||||
|
||||
_update_margins();
|
||||
|
||||
|
|
@ -164,7 +167,7 @@ void EditorDebuggerNode::_stack_frame_selected(int p_debugger) {
|
|||
void EditorDebuggerNode::_error_selected(const String &p_file, int p_line, int p_debugger) {
|
||||
if (!p_file.is_resource_file() && !ResourceCache::has(p_file)) {
|
||||
// If it's a built-in script, make sure the scene is opened first.
|
||||
EditorNode::get_singleton()->load_scene(p_file.get_slice("::", 0));
|
||||
EditorNode::get_singleton()->open_scene(p_file.get_slice("::", 0));
|
||||
}
|
||||
Ref<Script> s = ResourceLoader::load(p_file);
|
||||
emit_signal(SNAME("goto_script_line"), s, p_line - 1);
|
||||
|
|
@ -233,6 +236,12 @@ void EditorDebuggerNode::_bind_methods() {
|
|||
ADD_SIGNAL(MethodInfo("breakpoints_cleared_in_tree", PropertyInfo(Variant::INT, "debugger")));
|
||||
}
|
||||
|
||||
void EditorDebuggerNode::update_layout(EditorDock::DockLayout p_layout, int p_slot) {
|
||||
_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
|
||||
dbg->update_layout(p_layout, p_slot);
|
||||
});
|
||||
}
|
||||
|
||||
void EditorDebuggerNode::register_undo_redo(UndoRedo *p_undo_redo) {
|
||||
p_undo_redo->set_method_notify_callback(_methods_changed, this);
|
||||
p_undo_redo->set_property_notify_callback(_properties_changed, this);
|
||||
|
|
@ -308,6 +317,17 @@ void EditorDebuggerNode::stop(bool p_force) {
|
|||
inspect_edited_object_wait = false;
|
||||
|
||||
current_uri.clear();
|
||||
// Also close all debugging sessions.
|
||||
_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
|
||||
// If the server is also still active, let the debugger notify that it stopped.
|
||||
// Otherwise, just stop it silently.
|
||||
if (server.is_valid() || dbg->is_session_active()) {
|
||||
dbg->_stop_and_notify();
|
||||
} else {
|
||||
dbg->stop();
|
||||
}
|
||||
});
|
||||
|
||||
if (server.is_valid()) {
|
||||
server->stop();
|
||||
EditorNode::get_log()->add_message("--- Debugging process stopped ---", EditorLog::MSG_TYPE_EDITOR);
|
||||
|
|
@ -320,12 +340,6 @@ void EditorDebuggerNode::stop(bool p_force) {
|
|||
server.unref();
|
||||
}
|
||||
|
||||
// Also close all debugging sessions.
|
||||
_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
|
||||
if (dbg->is_session_active()) {
|
||||
dbg->_stop_and_notify();
|
||||
}
|
||||
});
|
||||
_break_state_changed();
|
||||
breakpoints.clear();
|
||||
EditorUndoRedoManager::get_singleton()->clear_history(EditorUndoRedoManager::REMOTE_HISTORY, false);
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ protected:
|
|||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
virtual void update_layout(EditorDock::DockLayout p_layout, int p_slot) override;
|
||||
|
||||
public:
|
||||
static EditorDebuggerNode *get_singleton() { return singleton; }
|
||||
void register_undo_redo(UndoRedo *p_undo_redo);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "editor_debugger_plugin.h"
|
||||
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "editor/debugger/script_editor_debugger.h"
|
||||
|
||||
void EditorDebuggerSession::_breaked(bool p_really_did, bool p_can_debug, const String &p_message, bool p_has_stackdump) {
|
||||
|
|
@ -107,13 +109,12 @@ void EditorDebuggerSession::set_breakpoint(const String &p_path, int p_line, boo
|
|||
}
|
||||
|
||||
void EditorDebuggerSession::detach_debugger() {
|
||||
if (!debugger) {
|
||||
if (!debugger || !ObjectDB::get_instance(debugger_id)) {
|
||||
return;
|
||||
}
|
||||
debugger->disconnect("started", callable_mp(this, &EditorDebuggerSession::_started));
|
||||
debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
|
||||
debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
|
||||
debugger->disconnect(SceneStringName(tree_exited), callable_mp(this, &EditorDebuggerSession::_debugger_gone_away));
|
||||
for (Control *tab : tabs) {
|
||||
debugger->remove_debugger_tab(tab);
|
||||
}
|
||||
|
|
@ -121,18 +122,13 @@ void EditorDebuggerSession::detach_debugger() {
|
|||
debugger = nullptr;
|
||||
}
|
||||
|
||||
void EditorDebuggerSession::_debugger_gone_away() {
|
||||
debugger = nullptr;
|
||||
tabs.clear();
|
||||
}
|
||||
|
||||
EditorDebuggerSession::EditorDebuggerSession(ScriptEditorDebugger *p_debugger) {
|
||||
ERR_FAIL_NULL(p_debugger);
|
||||
debugger = p_debugger;
|
||||
debugger_id = p_debugger->get_instance_id();
|
||||
debugger->connect("started", callable_mp(this, &EditorDebuggerSession::_started));
|
||||
debugger->connect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
|
||||
debugger->connect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
|
||||
debugger->connect(SceneStringName(tree_exited), callable_mp(this, &EditorDebuggerSession::_debugger_gone_away), CONNECT_ONE_SHOT);
|
||||
}
|
||||
|
||||
EditorDebuggerSession::~EditorDebuggerSession() {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "core/object/script_language.h"
|
||||
#include "scene/gui/control.h"
|
||||
|
||||
class ScriptEditorDebugger;
|
||||
|
|
@ -41,11 +43,11 @@ private:
|
|||
HashSet<Control *> tabs;
|
||||
|
||||
ScriptEditorDebugger *debugger = nullptr;
|
||||
ObjectID debugger_id;
|
||||
|
||||
void _breaked(bool p_really_did, bool p_can_debug, const String &p_message, bool p_has_stackdump);
|
||||
void _started();
|
||||
void _stopped();
|
||||
void _debugger_gone_away();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
|
|
|||
|
|
@ -58,12 +58,12 @@ public:
|
|||
|
||||
class EditorDebuggerServerTCP : public EditorDebuggerServerSocket<TCPServer> {
|
||||
public:
|
||||
static EditorDebuggerServer *create(const String &p_protocol);
|
||||
static Ref<EditorDebuggerServer> create(const String &p_protocol);
|
||||
|
||||
virtual Error start(const String &p_uri) override;
|
||||
};
|
||||
|
||||
EditorDebuggerServer *EditorDebuggerServerTCP::create(const String &p_protocol) {
|
||||
Ref<EditorDebuggerServer> EditorDebuggerServerTCP::create(const String &p_protocol) {
|
||||
ERR_FAIL_COND_V(p_protocol != "tcp://", nullptr);
|
||||
return memnew(EditorDebuggerServerTCP);
|
||||
}
|
||||
|
|
@ -138,12 +138,12 @@ Ref<RemoteDebuggerPeer> EditorDebuggerServerSocket<T>::take_connection() {
|
|||
|
||||
class EditorDebuggerServerUDS : public EditorDebuggerServerSocket<UDSServer> {
|
||||
public:
|
||||
static EditorDebuggerServer *create(const String &p_protocol);
|
||||
static Ref<EditorDebuggerServer> create(const String &p_protocol);
|
||||
|
||||
virtual Error start(const String &p_uri) override;
|
||||
};
|
||||
|
||||
EditorDebuggerServer *EditorDebuggerServerUDS::create(const String &p_protocol) {
|
||||
Ref<EditorDebuggerServer> EditorDebuggerServerUDS::create(const String &p_protocol) {
|
||||
ERR_FAIL_COND_V(p_protocol != "unix://", nullptr);
|
||||
return memnew(EditorDebuggerServerUDS);
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ Error EditorDebuggerServerUDS::start(const String &p_uri) {
|
|||
/// EditorDebuggerServer
|
||||
HashMap<StringName, EditorDebuggerServer::CreateServerFunc> EditorDebuggerServer::protocols;
|
||||
|
||||
EditorDebuggerServer *EditorDebuggerServer::create(const String &p_protocol) {
|
||||
Ref<EditorDebuggerServer> EditorDebuggerServer::create(const String &p_protocol) {
|
||||
CreateServerFunc *create_fn = protocols.getptr(p_protocol);
|
||||
ERR_FAIL_NULL_V(create_fn, nullptr);
|
||||
return (*create_fn)(p_protocol);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class EditorDebuggerServer : public RefCounted {
|
|||
GDSOFTCLASS(EditorDebuggerServer, RefCounted);
|
||||
|
||||
public:
|
||||
typedef EditorDebuggerServer *(*CreateServerFunc)(const String &p_uri);
|
||||
typedef Ref<EditorDebuggerServer> (*CreateServerFunc)(const String &p_uri);
|
||||
|
||||
private:
|
||||
static HashMap<StringName, CreateServerFunc> protocols;
|
||||
|
|
@ -47,7 +47,7 @@ public:
|
|||
static void deinitialize();
|
||||
|
||||
static void register_protocol_handler(const String &p_protocol, CreateServerFunc p_func);
|
||||
static EditorDebuggerServer *create(const String &p_protocol);
|
||||
static Ref<EditorDebuggerServer> create(const String &p_protocol);
|
||||
|
||||
virtual String get_uri() const = 0;
|
||||
virtual void poll() = 0;
|
||||
|
|
|
|||
|
|
@ -30,14 +30,18 @@
|
|||
|
||||
#include "editor_debugger_tree.h"
|
||||
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "editor/debugger/editor_debugger_node.h"
|
||||
#include "editor/docks/inspector_dock.h"
|
||||
#include "editor/docks/scene_tree_dock.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
#include "editor/gui/editor_file_dialog.h"
|
||||
#include "editor/gui/editor_toaster.h"
|
||||
#include "editor/settings/editor_settings.h"
|
||||
#include "scene/debugger/scene_debugger.h"
|
||||
#include "scene/debugger/scene_debugger_object.h"
|
||||
#include "scene/gui/texture_rect.h"
|
||||
#include "scene/resources/packed_scene.h"
|
||||
#include "servers/display/display_server.h"
|
||||
|
|
@ -58,6 +62,7 @@ EditorDebuggerTree::EditorDebuggerTree() {
|
|||
add_child(file_dialog);
|
||||
|
||||
accept = memnew(AcceptDialog);
|
||||
accept->set_flag(Window::FLAG_RESIZE_DISABLED, true);
|
||||
add_child(accept);
|
||||
}
|
||||
|
||||
|
|
@ -279,18 +284,15 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
|
|||
if (debugger_id == p_debugger) { // Can use remote id.
|
||||
if (inspected_object_ids.has(uint64_t(node.id))) {
|
||||
ids_present.append(node.id);
|
||||
|
||||
if (selection_uncollapse_all) {
|
||||
selection_uncollapse_all = false;
|
||||
|
||||
// Temporarily set to `false`, to allow caching the unfolds.
|
||||
updating_scene_tree = false;
|
||||
item->uncollapse_tree();
|
||||
updating_scene_tree = true;
|
||||
}
|
||||
|
||||
select_items.push_back(item);
|
||||
if (should_scroll) {
|
||||
// Temporarily set to `false`, to allow caching the unfolds.
|
||||
updating_scene_tree = false;
|
||||
// Expand ancestors to make the item visible.
|
||||
if (TreeItem *parent_item = item->get_parent()) {
|
||||
parent_item->uncollapse_tree();
|
||||
}
|
||||
updating_scene_tree = true;
|
||||
scroll_item = item;
|
||||
}
|
||||
}
|
||||
|
|
@ -412,10 +414,18 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
|
|||
|
||||
void EditorDebuggerTree::select_nodes(const TypedArray<int64_t> &p_ids) {
|
||||
// Manually select, as the tree control may be out-of-date for some reason (e.g. not shown yet).
|
||||
selection_uncollapse_all = true;
|
||||
inspected_object_ids = p_ids;
|
||||
scrolling_to_item = true;
|
||||
|
||||
// If we have not previously selected any of these items, expand the inspector's properties for this item.
|
||||
for (ObjectID id : p_ids) {
|
||||
if (!selection_cache.has(id)) {
|
||||
selection_cache.insert(id);
|
||||
|
||||
InspectorDock::get_inspector_singleton()->expand_all_folding();
|
||||
}
|
||||
}
|
||||
|
||||
if (!updating_scene_tree) {
|
||||
// Request a tree refresh.
|
||||
EditorDebuggerNode::get_singleton()->request_remote_tree();
|
||||
|
|
@ -471,6 +481,11 @@ Variant EditorDebuggerTree::get_drag_data(const Point2 &p_point) {
|
|||
return vformat("\"%s\"", path);
|
||||
}
|
||||
|
||||
void EditorDebuggerTree::set_new_session() {
|
||||
new_session = true;
|
||||
selection_cache.clear();
|
||||
}
|
||||
|
||||
void EditorDebuggerTree::update_icon_max_width() {
|
||||
add_theme_constant_override("icon_max_width", get_theme_constant("class_icon_size", EditorStringName(Editor)));
|
||||
}
|
||||
|
|
@ -504,16 +519,12 @@ void EditorDebuggerTree::_item_menu_id_pressed(int p_option) {
|
|||
String text = get_selected_path();
|
||||
if (text.is_empty()) {
|
||||
return;
|
||||
} else if (text == "/root") {
|
||||
}
|
||||
// Keep full remote path but strip the "/root" prefix for user-facing copy.
|
||||
if (text == "/root") {
|
||||
text = ".";
|
||||
} else {
|
||||
text = text.replace("/root/", "");
|
||||
int slash = text.find_char('/');
|
||||
if (slash < 0) {
|
||||
text = ".";
|
||||
} else {
|
||||
text = text.substr(slash + 1);
|
||||
}
|
||||
} else if (text.begins_with("/root/")) {
|
||||
text = text.substr(String("/root/").length());
|
||||
}
|
||||
DisplayServer::get_singleton()->clipboard_set(text);
|
||||
} break;
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ private:
|
|||
bool scrolling_to_item = false;
|
||||
bool notify_selection_queued = false;
|
||||
bool selection_surpassed_limit = false;
|
||||
bool selection_uncollapse_all = false;
|
||||
HashSet<ObjectID> unfold_cache;
|
||||
HashSet<ObjectID> selection_cache;
|
||||
PopupMenu *item_menu = nullptr;
|
||||
EditorFileDialog *file_dialog = nullptr;
|
||||
AcceptDialog *accept = nullptr;
|
||||
|
|
@ -93,7 +93,7 @@ public:
|
|||
|
||||
virtual Variant get_drag_data(const Point2 &p_point) override;
|
||||
|
||||
void set_new_session() { new_session = true; }
|
||||
void set_new_session();
|
||||
void update_icon_max_width();
|
||||
String get_selected_path();
|
||||
ObjectID get_selected_object();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "editor_expression_evaluator.h"
|
||||
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "editor/debugger/editor_debugger_inspector.h"
|
||||
#include "editor/debugger/script_editor_debugger.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "editor_performance_profiler.h"
|
||||
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/string/translation_server.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
#include "editor/inspector/editor_property_name_processor.h"
|
||||
|
|
@ -403,7 +404,7 @@ void EditorPerformanceProfiler::_notification(int p_what) {
|
|||
} break;
|
||||
|
||||
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
|
||||
if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
|
||||
if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localization/localize_settings")) {
|
||||
_build_monitor_tree();
|
||||
}
|
||||
} break;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "editor_profiler.h"
|
||||
|
||||
#include "core/io/image.h"
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/string/translation_server.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
#include "editor/run/editor_run_bar.h"
|
||||
|
|
@ -38,6 +39,7 @@
|
|||
#include "editor/themes/editor_scale.h"
|
||||
#include "scene/gui/check_box.h"
|
||||
#include "scene/gui/flow_container.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/resources/image_texture.h"
|
||||
|
||||
void EditorProfiler::_make_metric_ptrs(Metric &m) {
|
||||
|
|
@ -49,7 +51,7 @@ void EditorProfiler::_make_metric_ptrs(Metric &m) {
|
|||
}
|
||||
}
|
||||
|
||||
EditorProfiler::Metric EditorProfiler::_get_frame_metric(int index) {
|
||||
const EditorProfiler::Metric &EditorProfiler::_get_frame_metric(int index) const {
|
||||
return frame_metrics[(frame_metrics.size() + last_metric - (total_metrics - 1) + index) % frame_metrics.size()];
|
||||
}
|
||||
|
||||
|
|
@ -186,6 +188,20 @@ void EditorProfiler::_item_edited() {
|
|||
_update_plot();
|
||||
}
|
||||
|
||||
void EditorProfiler::_item_collapsed(TreeItem *p_item) {
|
||||
if (!p_item) {
|
||||
return;
|
||||
}
|
||||
StringName signature = p_item->get_metadata(0);
|
||||
bool collapsed = p_item->is_collapsed();
|
||||
|
||||
if (collapsed) {
|
||||
collapsed_categories.insert(signature);
|
||||
} else {
|
||||
collapsed_categories.erase(signature);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorProfiler::_update_plot() {
|
||||
const int w = MAX(1, graph->get_size().width); // Clamp to 1 to prevent from crashing when profiler is autostarted.
|
||||
const int h = MAX(1, graph->get_size().height);
|
||||
|
|
@ -362,6 +378,10 @@ void EditorProfiler::_update_frame() {
|
|||
category->set_auto_translate_mode(0, AUTO_TRANSLATE_MODE_DISABLED);
|
||||
category->set_text(1, _get_time_as_text(m, m.categories[i].total_time, 1));
|
||||
|
||||
if (collapsed_categories.has(m.categories[i].signature)) {
|
||||
category->set_collapsed(true);
|
||||
}
|
||||
|
||||
if (plot_sigs.has(m.categories[i].signature)) {
|
||||
category->set_checked(0, true);
|
||||
category->set_custom_color(0, _get_color_from_signature(m.categories[i].signature));
|
||||
|
|
@ -755,7 +775,6 @@ EditorProfiler::EditorProfiler() {
|
|||
|
||||
variables = memnew(Tree);
|
||||
variables->set_custom_minimum_size(Size2(320, 0) * EDSCALE);
|
||||
variables->set_hide_folding(true);
|
||||
h_split->add_child(variables);
|
||||
variables->set_hide_root(true);
|
||||
variables->set_columns(3);
|
||||
|
|
@ -774,6 +793,7 @@ EditorProfiler::EditorProfiler() {
|
|||
variables->set_column_custom_minimum_width(2, 50 * EDSCALE);
|
||||
variables->set_theme_type_variation("TreeSecondary");
|
||||
variables->connect("item_edited", callable_mp(this, &EditorProfiler::_item_edited));
|
||||
variables->connect("item_collapsed", callable_mp(this, &EditorProfiler::_item_collapsed));
|
||||
|
||||
graph = memnew(TextureRect);
|
||||
graph->set_custom_minimum_size(Size2(250 * EDSCALE, 0));
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/check_button.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/option_button.h"
|
||||
#include "scene/gui/spin_box.h"
|
||||
#include "scene/gui/split_container.h"
|
||||
|
|
@ -112,6 +111,7 @@ private:
|
|||
HSplitContainer *h_split = nullptr;
|
||||
|
||||
HashSet<StringName> plot_sigs;
|
||||
HashSet<StringName> collapsed_categories;
|
||||
|
||||
OptionButton *display_mode = nullptr;
|
||||
OptionButton *display_time = nullptr;
|
||||
|
|
@ -148,6 +148,7 @@ private:
|
|||
|
||||
void _make_metric_ptrs(Metric &m);
|
||||
void _item_edited();
|
||||
void _item_collapsed(TreeItem *p_item);
|
||||
|
||||
void _update_plot();
|
||||
|
||||
|
|
@ -163,7 +164,7 @@ private:
|
|||
|
||||
void _combo_changed(int);
|
||||
|
||||
Metric _get_frame_metric(int index);
|
||||
const Metric &_get_frame_metric(int index) const;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
|
|
|||
|
|
@ -31,12 +31,14 @@
|
|||
#include "editor_visual_profiler.h"
|
||||
|
||||
#include "core/io/image.h"
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/string/translation_server.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
#include "editor/run/editor_run_bar.h"
|
||||
#include "editor/settings/editor_settings.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
#include "scene/gui/flow_container.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/resources/image_texture.h"
|
||||
|
||||
void EditorVisualProfiler::set_hardware_info(const String &p_cpu_name, const String &p_gpu_name) {
|
||||
|
|
@ -111,6 +113,7 @@ void EditorVisualProfiler::clear() {
|
|||
last_metric = -1;
|
||||
variables->clear();
|
||||
//activate->set_pressed(false);
|
||||
category_folding.clear();
|
||||
|
||||
graph_limit = 1000.0f / CLAMP(int(EDITOR_GET("debugger/profiler_target_fps")), 1, 1000);
|
||||
|
||||
|
|
@ -158,6 +161,11 @@ void EditorVisualProfiler::_item_selected() {
|
|||
_update_plot();
|
||||
}
|
||||
|
||||
void EditorVisualProfiler::_item_collapsed(TreeItem *p_item) {
|
||||
StringName fullpath = p_item->get_metadata(0);
|
||||
category_folding[fullpath] = p_item->is_collapsed();
|
||||
}
|
||||
|
||||
void EditorVisualProfiler::_update_plot() {
|
||||
const int w = graph->get_size().width + 1; // `+1` is to prevent from crashing when visual profiler is auto started.
|
||||
const int h = graph->get_size().height + 1;
|
||||
|
|
@ -367,9 +375,14 @@ void EditorVisualProfiler::_update_frame(bool p_focus_selected) {
|
|||
|
||||
name = name.substr(1);
|
||||
|
||||
category->set_metadata(0, m.areas[i].fullpath_cache);
|
||||
category->set_text(0, name);
|
||||
category->set_metadata(1, cpu_time);
|
||||
category->set_metadata(2, gpu_time);
|
||||
|
||||
if (category_folding.has(m.areas[i].fullpath_cache)) {
|
||||
category->set_collapsed(category_folding[m.areas[i].fullpath_cache]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -414,6 +427,13 @@ void EditorVisualProfiler::_update_frame(bool p_focus_selected) {
|
|||
}
|
||||
|
||||
if (ensure_selected) {
|
||||
// Make visible when it's collapsed.
|
||||
TreeItem *node = ensure_selected->get_parent();
|
||||
while (node) {
|
||||
node->set_collapsed(false);
|
||||
node = node->get_parent();
|
||||
}
|
||||
ensure_selected->select(0);
|
||||
variables->ensure_cursor_is_visible();
|
||||
}
|
||||
updating_frame = false;
|
||||
|
|
@ -467,25 +487,30 @@ void EditorVisualProfiler::_graph_tex_draw() {
|
|||
Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
|
||||
int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
|
||||
const Color color = get_theme_color(SceneStringName(font_color), EditorStringName(Editor));
|
||||
Size2 graph_size = graph->get_size();
|
||||
|
||||
if (seeking) {
|
||||
int max_frames = frame_metrics.size();
|
||||
int frame = cursor_metric_edit->get_value() - (frame_metrics[last_metric].frame_number - max_frames + 1);
|
||||
|
||||
int64_t first_visible_frame = static_cast<int64_t>(frame_metrics[last_metric].frame_number) - max_frames + 1;
|
||||
int frame = (cursor_metric_edit->get_value() - first_visible_frame);
|
||||
if (frame < 0) {
|
||||
frame = 0;
|
||||
}
|
||||
|
||||
int half_width = graph->get_size().x / 2;
|
||||
int half_width = graph_size.x / 2;
|
||||
int cur_x = frame * half_width / max_frames;
|
||||
|
||||
graph->draw_line(Vector2(cur_x, 0), Vector2(cur_x, graph->get_size().y), color * Color(1, 1, 1));
|
||||
graph->draw_line(Vector2(cur_x + half_width, 0), Vector2(cur_x + half_width, graph->get_size().y), color * Color(1, 1, 1));
|
||||
graph->draw_line(Vector2(cur_x, 0), Vector2(cur_x, graph_size.y), color * Color(1, 1, 1));
|
||||
graph->draw_line(Vector2(cur_x + half_width, 0), Vector2(cur_x + half_width, graph_size.y), color * Color(1, 1, 1));
|
||||
}
|
||||
|
||||
if (graph_height_cpu > 0) {
|
||||
int frame_y = graph->get_size().y - graph_limit * graph->get_size().y / graph_height_cpu - 1;
|
||||
int cpu_height = graph_limit * graph_size.y / graph_height_cpu;
|
||||
cpu_height = CLAMP(cpu_height, 0, graph_size.y - (font->get_ascent(font_size) + 2) * 2);
|
||||
int frame_y = graph_size.y - cpu_height - 1;
|
||||
|
||||
int half_width = graph->get_size().x / 2;
|
||||
int half_width = graph_size.x / 2;
|
||||
|
||||
graph->draw_line(Vector2(0, frame_y), Vector2(half_width, frame_y), color * Color(1, 1, 1, 0.5));
|
||||
|
||||
|
|
@ -494,18 +519,20 @@ void EditorVisualProfiler::_graph_tex_draw() {
|
|||
}
|
||||
|
||||
if (graph_height_gpu > 0) {
|
||||
int frame_y = graph->get_size().y - graph_limit * graph->get_size().y / graph_height_gpu - 1;
|
||||
int gpu_height = graph_limit * graph_size.y / graph_height_gpu;
|
||||
gpu_height = CLAMP(gpu_height, 0, graph_size.y - (font->get_ascent(font_size) + 2) * 2);
|
||||
int frame_y = graph_size.y - gpu_height - 1;
|
||||
|
||||
int half_width = graph->get_size().x / 2;
|
||||
int half_width = graph_size.x / 2;
|
||||
|
||||
graph->draw_line(Vector2(half_width, frame_y), Vector2(graph->get_size().x, frame_y), color * Color(1, 1, 1, 0.5));
|
||||
graph->draw_line(Vector2(half_width, frame_y), Vector2(graph_size.x, frame_y), color * Color(1, 1, 1, 0.5));
|
||||
|
||||
const String limit_str = String::num(graph_limit, 2) + " ms";
|
||||
graph->draw_string(font, Vector2(half_width * 2 - font->get_string_size(limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
|
||||
}
|
||||
|
||||
graph->draw_string(font, Vector2(font->get_string_size("X", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x, font->get_ascent(font_size) + 2), "CPU: " + cpu_name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
|
||||
graph->draw_string(font, Vector2(font->get_string_size("X", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + graph->get_size().width / 2, font->get_ascent(font_size) + 2), "GPU: " + gpu_name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
|
||||
graph->draw_string(font, Vector2(font->get_string_size("X", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + graph_size.width / 2, font->get_ascent(font_size) + 2), "GPU: " + gpu_name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
|
||||
}
|
||||
|
||||
void EditorVisualProfiler::_graph_tex_mouse_exit() {
|
||||
|
|
@ -820,7 +847,6 @@ EditorVisualProfiler::EditorVisualProfiler() {
|
|||
|
||||
variables = memnew(Tree);
|
||||
variables->set_custom_minimum_size(Size2(300, 0) * EDSCALE);
|
||||
variables->set_hide_folding(true);
|
||||
h_split->add_child(variables);
|
||||
variables->set_hide_root(true);
|
||||
variables->set_columns(3);
|
||||
|
|
@ -839,6 +865,7 @@ EditorVisualProfiler::EditorVisualProfiler() {
|
|||
variables->set_column_custom_minimum_width(2, 75 * EDSCALE);
|
||||
variables->set_theme_type_variation("TreeSecondary");
|
||||
variables->connect("cell_selected", callable_mp(this, &EditorVisualProfiler::_item_selected));
|
||||
variables->connect("item_collapsed", callable_mp(this, &EditorVisualProfiler::_item_collapsed));
|
||||
|
||||
graph = memnew(TextureRect);
|
||||
graph->set_custom_minimum_size(Size2(250 * EDSCALE, 0));
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/check_box.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/option_button.h"
|
||||
#include "scene/gui/spin_box.h"
|
||||
#include "scene/gui/split_container.h"
|
||||
|
|
@ -89,6 +88,7 @@ private:
|
|||
int hover_metric = -1;
|
||||
|
||||
StringName selected_area;
|
||||
HashMap<StringName, bool> category_folding;
|
||||
|
||||
bool updating_frame = false;
|
||||
|
||||
|
|
@ -117,6 +117,7 @@ private:
|
|||
|
||||
//void _make_metric_ptrs(Metric &m);
|
||||
void _item_selected();
|
||||
void _item_collapsed(TreeItem *p_item);
|
||||
|
||||
void _update_plot();
|
||||
|
||||
|
|
|
|||
|
|
@ -30,9 +30,15 @@
|
|||
|
||||
#include "script_editor_debugger.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/debugger/debugger_marshalls.h"
|
||||
#include "core/debugger/remote_debugger.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/variant/typed_dictionary.h"
|
||||
#include "core/version.h"
|
||||
#include "editor/debugger/editor_debugger_plugin.h"
|
||||
#include "editor/debugger/editor_expression_evaluator.h"
|
||||
|
|
@ -49,12 +55,13 @@
|
|||
#include "editor/gui/editor_toaster.h"
|
||||
#include "editor/inspector/editor_property_name_processor.h"
|
||||
#include "editor/scene/3d/node_3d_editor_plugin.h"
|
||||
#include "editor/scene/3d/node_3d_editor_viewport.h"
|
||||
#include "editor/scene/canvas_item_editor_plugin.h"
|
||||
#include "editor/settings/editor_settings.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
#include "main/performance.h"
|
||||
#include "scene/3d/camera_3d.h"
|
||||
#include "scene/debugger/scene_debugger.h"
|
||||
#include "scene/debugger/scene_debugger_object.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/dialogs.h"
|
||||
#include "scene/gui/grid_container.h"
|
||||
|
|
@ -654,6 +661,7 @@ void ScriptEditorDebugger::_msg_error(uint64_t p_thread_id, const Array &p_data)
|
|||
}
|
||||
error->set_collapsed(true);
|
||||
|
||||
error->set_text_overrun_behavior(0, TextServer::OVERRUN_NO_TRIMMING);
|
||||
error->set_icon(0, get_editor_theme_icon(oe.warning ? SNAME("Warning") : SNAME("Error")));
|
||||
error->set_text(0, time);
|
||||
error->set_text_alignment(0, HORIZONTAL_ALIGNMENT_LEFT);
|
||||
|
|
@ -678,6 +686,7 @@ void ScriptEditorDebugger::_msg_error(uint64_t p_thread_id, const Array &p_data)
|
|||
error_title += oe.error_descr.is_empty() ? oe.error : oe.error_descr;
|
||||
error->set_text(1, error_title);
|
||||
error->set_autowrap_mode(1, TextServer::AUTOWRAP_WORD_SMART);
|
||||
error->set_autowrap_trim_flags(1, 0);
|
||||
tooltip += " " + error_title + "\n";
|
||||
|
||||
// Find the language of the error's source file.
|
||||
|
|
@ -1112,11 +1121,20 @@ void ScriptEditorDebugger::_notification(int p_what) {
|
|||
vmem_notice_icon->set_texture(get_editor_theme_icon(SNAME("NodeInfo")));
|
||||
vmem_refresh->set_button_icon(get_editor_theme_icon(SNAME("Reload")));
|
||||
vmem_export->set_button_icon(get_editor_theme_icon(SNAME("Save")));
|
||||
vmem_item_menu->set_item_icon(VMEM_MENU_SHOW_IN_FILESYSTEM, get_editor_theme_icon(SNAME("ShowInFileSystem")));
|
||||
vmem_item_menu->set_item_icon(VMEM_MENU_SHOW_IN_EXPLORER, get_editor_theme_icon(SNAME("Filesystem")));
|
||||
search->set_right_icon(get_editor_theme_icon(SNAME("Search")));
|
||||
|
||||
reason->add_theme_color_override(SNAME("default_color"), get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
|
||||
reason->add_theme_style_override(SNAME("normal"), get_theme_stylebox(SNAME("normal"), SNAME("Label"))); // Empty stylebox.
|
||||
|
||||
const Ref<Font> source_font = get_theme_font(SNAME("output_source"), EditorStringName(EditorFonts));
|
||||
if (source_font.is_valid()) {
|
||||
error_tree->add_theme_font_override("font", source_font);
|
||||
}
|
||||
const int font_size = get_theme_font_size(SNAME("output_source_size"), EditorStringName(EditorFonts));
|
||||
error_tree->add_theme_font_size_override("font_size", font_size);
|
||||
|
||||
TreeItem *error_root = error_tree->get_root();
|
||||
if (error_root) {
|
||||
TreeItem *error = error_root->get_first_child();
|
||||
|
|
@ -1836,6 +1854,45 @@ void ScriptEditorDebugger::_vmem_item_activated() {
|
|||
FileSystemDock::get_singleton()->navigate_to_path(path);
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::_vmem_tree_rmb_selected(const Vector2 &p_pos, MouseButton p_button) {
|
||||
if (p_button != MouseButton::RIGHT) {
|
||||
return;
|
||||
}
|
||||
|
||||
TreeItem *item = vmem_tree->get_selected();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
String path = item->get_text(0);
|
||||
if (path.is_empty() || !FileAccess::exists(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vmem_item_menu->set_position(vmem_tree->get_screen_position() + p_pos);
|
||||
vmem_item_menu->popup();
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::_vmem_item_menu_id_pressed(int p_option) {
|
||||
TreeItem *item = vmem_tree->get_selected();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
String path = item->get_text(0);
|
||||
switch (p_option) {
|
||||
case VMEM_MENU_SHOW_IN_FILESYSTEM: {
|
||||
FileSystemDock::get_singleton()->navigate_to_path(path);
|
||||
} break;
|
||||
case VMEM_MENU_SHOW_IN_EXPLORER: {
|
||||
OS::get_singleton()->shell_show_in_file_manager(ProjectSettings::get_singleton()->globalize_path(path), true);
|
||||
} break;
|
||||
case VMEM_MENU_OWNERS: {
|
||||
FileSystemDock::get_owners_dialog()->show(path);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::_clear_errors_list() {
|
||||
error_tree->clear();
|
||||
error_count = 0;
|
||||
|
|
@ -2050,6 +2107,16 @@ void ScriptEditorDebugger::toggle_profiler(const String &p_profiler, bool p_enab
|
|||
_put_msg("profiler:" + p_profiler, msg_data);
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::update_layout(EditorDock::DockLayout p_layout, int p_slot) {
|
||||
if (p_slot != EditorDock::DOCK_SLOT_BOTTOM) {
|
||||
vmem_mc->set_theme_type_variation("NoBorderHorizontalBottom");
|
||||
vmem_tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_DISABLED);
|
||||
} else {
|
||||
vmem_mc->set_theme_type_variation("NoBorderHorizontal");
|
||||
vmem_tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_BOTTOM);
|
||||
}
|
||||
}
|
||||
|
||||
ScriptEditorDebugger::ScriptEditorDebugger() {
|
||||
if (unlikely(parse_message_handlers.is_empty())) {
|
||||
_init_parse_message_handlers();
|
||||
|
|
@ -2076,66 +2143,70 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
|
|||
reason->set_context_menu_enabled(true);
|
||||
reason->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
reason->set_v_size_flags(SIZE_SHRINK_CENTER);
|
||||
reason->connect(SceneStringName(resized), callable_mp(this, &ScriptEditorDebugger::_update_reason_content_height));
|
||||
reason->connect(SceneStringName(resized), callable_mp(this, &ScriptEditorDebugger::_update_reason_content_height), CONNECT_DEFERRED);
|
||||
hbc->add_child(reason);
|
||||
|
||||
hbc->add_child(memnew(VSeparator));
|
||||
HBoxContainer *buttons = memnew(HBoxContainer);
|
||||
buttons->set_v_size_flags(SIZE_SHRINK_END);
|
||||
hbc->add_child(buttons);
|
||||
|
||||
buttons->add_child(memnew(VSeparator));
|
||||
|
||||
skip_breakpoints = memnew(Button);
|
||||
skip_breakpoints->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
hbc->add_child(skip_breakpoints);
|
||||
buttons->add_child(skip_breakpoints);
|
||||
skip_breakpoints->set_tooltip_text(TTRC("Skip Breakpoints"));
|
||||
skip_breakpoints->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::debug_skip_breakpoints));
|
||||
|
||||
ignore_error_breaks = memnew(Button);
|
||||
ignore_error_breaks->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
ignore_error_breaks->set_tooltip_text(TTRC("Ignore Error Breaks"));
|
||||
hbc->add_child(ignore_error_breaks);
|
||||
buttons->add_child(ignore_error_breaks);
|
||||
ignore_error_breaks->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::debug_ignore_error_breaks));
|
||||
|
||||
hbc->add_child(memnew(VSeparator));
|
||||
buttons->add_child(memnew(VSeparator));
|
||||
|
||||
copy = memnew(Button);
|
||||
copy->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
hbc->add_child(copy);
|
||||
buttons->add_child(copy);
|
||||
copy->set_tooltip_text(TTRC("Copy Error"));
|
||||
copy->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::debug_copy));
|
||||
|
||||
hbc->add_child(memnew(VSeparator));
|
||||
buttons->add_child(memnew(VSeparator));
|
||||
|
||||
step = memnew(Button);
|
||||
step->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
hbc->add_child(step);
|
||||
buttons->add_child(step);
|
||||
step->set_tooltip_text(TTRC("Step Into"));
|
||||
step->set_shortcut(ED_GET_SHORTCUT("debugger/step_into"));
|
||||
step->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::debug_step));
|
||||
|
||||
next = memnew(Button);
|
||||
next->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
hbc->add_child(next);
|
||||
buttons->add_child(next);
|
||||
next->set_tooltip_text(TTRC("Step Over"));
|
||||
next->set_shortcut(ED_GET_SHORTCUT("debugger/step_over"));
|
||||
next->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::debug_next));
|
||||
|
||||
out = memnew(Button);
|
||||
out->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
hbc->add_child(out);
|
||||
buttons->add_child(out);
|
||||
out->set_tooltip_text(TTRC("Step Out"));
|
||||
out->set_shortcut(ED_GET_SHORTCUT("debugger/step_out"));
|
||||
out->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::debug_out));
|
||||
|
||||
hbc->add_child(memnew(VSeparator));
|
||||
buttons->add_child(memnew(VSeparator));
|
||||
|
||||
dobreak = memnew(Button);
|
||||
dobreak->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
hbc->add_child(dobreak);
|
||||
buttons->add_child(dobreak);
|
||||
dobreak->set_tooltip_text(TTRC("Break"));
|
||||
dobreak->set_shortcut(ED_GET_SHORTCUT("debugger/break"));
|
||||
dobreak->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::debug_break));
|
||||
|
||||
docontinue = memnew(Button);
|
||||
docontinue->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
hbc->add_child(docontinue);
|
||||
buttons->add_child(docontinue);
|
||||
docontinue->set_tooltip_text(TTRC("Continue"));
|
||||
docontinue->set_shortcut(ED_GET_SHORTCUT("debugger/continue"));
|
||||
docontinue->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::debug_continue));
|
||||
|
|
@ -2251,7 +2322,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
|
|||
|
||||
error_tree->set_column_expand(0, false);
|
||||
error_tree->set_column_custom_minimum_width(0, 140);
|
||||
error_tree->set_column_clip_content(0, true);
|
||||
error_tree->set_column_clip_content(0, false);
|
||||
|
||||
error_tree->set_column_expand(1, true);
|
||||
error_tree->set_column_clip_content(1, true);
|
||||
|
|
@ -2354,10 +2425,10 @@ Instead, use the monitors tab to obtain more precise VRAM usage.
|
|||
vmem_refresh->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::_video_mem_request));
|
||||
vmem_export->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::_video_mem_export));
|
||||
|
||||
MarginContainer *mc = memnew(MarginContainer);
|
||||
mc->set_theme_type_variation("NoBorderBottomPanel");
|
||||
mc->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
vmem_vb->add_child(mc);
|
||||
vmem_mc = memnew(MarginContainer);
|
||||
vmem_mc->set_theme_type_variation("NoBorderHorizontal");
|
||||
vmem_mc->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
vmem_vb->add_child(vmem_mc);
|
||||
|
||||
vmem_tree = memnew(Tree);
|
||||
vmem_vb->set_name(TTRC("Video RAM"));
|
||||
|
|
@ -2376,10 +2447,18 @@ Instead, use the monitors tab to obtain more precise VRAM usage.
|
|||
vmem_tree->set_column_custom_minimum_width(3, 80 * EDSCALE);
|
||||
vmem_tree->set_hide_root(true);
|
||||
vmem_tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_BOTTOM);
|
||||
mc->add_child(vmem_tree);
|
||||
vmem_mc->add_child(vmem_tree);
|
||||
vmem_tree->set_allow_rmb_select(true);
|
||||
vmem_tree->connect("item_activated", callable_mp(this, &ScriptEditorDebugger::_vmem_item_activated));
|
||||
|
||||
vmem_tree->connect("item_mouse_selected", callable_mp(this, &ScriptEditorDebugger::_vmem_tree_rmb_selected));
|
||||
tabs->add_child(vmem_vb);
|
||||
|
||||
vmem_item_menu = memnew(PopupMenu);
|
||||
vmem_item_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ScriptEditorDebugger::_vmem_item_menu_id_pressed));
|
||||
vmem_item_menu->add_item(TTRC("Show in FileSystem"), VMEM_MENU_SHOW_IN_FILESYSTEM);
|
||||
vmem_item_menu->add_item(OS::get_singleton()->get_platform_string(OS::PLATFORM_STRING_FILE_MANAGER_SHOW), VMEM_MENU_SHOW_IN_EXPLORER);
|
||||
vmem_item_menu->add_item(TTRC("View Owners..."), VMEM_MENU_OWNERS);
|
||||
add_child(vmem_item_menu);
|
||||
}
|
||||
|
||||
{ // misc
|
||||
|
|
@ -2422,7 +2501,7 @@ Instead, use the monitors tab to obtain more precise VRAM usage.
|
|||
info_left->add_child(lehb);
|
||||
}
|
||||
|
||||
misc->add_child(memnew(VSeparator));
|
||||
misc->add_child(memnew(HSeparator));
|
||||
|
||||
HBoxContainer *buttons = memnew(HBoxContainer);
|
||||
|
||||
|
|
@ -2436,9 +2515,6 @@ Instead, use the monitors tab to obtain more precise VRAM usage.
|
|||
msgdialog = memnew(AcceptDialog);
|
||||
add_child(msgdialog);
|
||||
|
||||
camera_override = CameraOverride::OVERRIDE_NONE;
|
||||
error_count = 0;
|
||||
warning_count = 0;
|
||||
_update_buttons_state();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/object/script_language.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/os/process_id.h"
|
||||
#include "editor/debugger/editor_debugger_inspector.h"
|
||||
#include "editor/debugger/editor_debugger_node.h"
|
||||
#include "scene/gui/margin_container.h"
|
||||
|
|
@ -83,6 +83,12 @@ private:
|
|||
ACTION_DELETE_ALL_BREAKPOINTS,
|
||||
};
|
||||
|
||||
enum VMemMenu {
|
||||
VMEM_MENU_SHOW_IN_FILESYSTEM,
|
||||
VMEM_MENU_SHOW_IN_EXPLORER,
|
||||
VMEM_MENU_OWNERS,
|
||||
};
|
||||
|
||||
AcceptDialog *msgdialog = nullptr;
|
||||
|
||||
LineEdit *clicked_ctrl = nullptr;
|
||||
|
|
@ -109,8 +115,8 @@ private:
|
|||
};
|
||||
FileDialogPurpose file_dialog_purpose = SAVE_MONITORS_CSV;
|
||||
|
||||
int error_count;
|
||||
int warning_count;
|
||||
int error_count = 0;
|
||||
int warning_count = 0;
|
||||
|
||||
bool skip_breakpoints_value = false;
|
||||
bool ignore_error_breaks_value = false;
|
||||
|
|
@ -134,11 +140,13 @@ private:
|
|||
|
||||
HashMap<int, String> profiler_signature;
|
||||
|
||||
MarginContainer *vmem_mc = nullptr;
|
||||
Tree *vmem_tree = nullptr;
|
||||
Button *vmem_refresh = nullptr;
|
||||
Button *vmem_export = nullptr;
|
||||
LineEdit *vmem_total = nullptr;
|
||||
TextureRect *vmem_notice_icon = nullptr;
|
||||
PopupMenu *vmem_item_menu = nullptr;
|
||||
|
||||
Tree *stack_dump = nullptr;
|
||||
LineEdit *search = nullptr;
|
||||
|
|
@ -157,7 +165,7 @@ private:
|
|||
EditorPerformanceProfiler *performance_profiler = nullptr;
|
||||
EditorExpressionEvaluator *expression_evaluator = nullptr;
|
||||
|
||||
OS::ProcessID remote_pid = 0;
|
||||
ProcessID remote_pid = 0;
|
||||
bool move_to_foreground = true;
|
||||
bool can_request_idle_draw = false;
|
||||
|
||||
|
|
@ -190,7 +198,7 @@ private:
|
|||
void _mute_audio_on_break(bool p_mute);
|
||||
void _send_debug_mute_audio_msg(bool p_mute);
|
||||
|
||||
EditorDebuggerNode::CameraOverride camera_override;
|
||||
EditorDebuggerNode::CameraOverride camera_override = EditorDebuggerNode::OVERRIDE_NONE;
|
||||
|
||||
void _stack_dump_frame_selected();
|
||||
|
||||
|
|
@ -267,6 +275,8 @@ private:
|
|||
void _collapse_errors_list();
|
||||
|
||||
void _vmem_item_activated();
|
||||
void _vmem_tree_rmb_selected(const Vector2 &p_pos, MouseButton p_button);
|
||||
void _vmem_item_menu_id_pressed(int p_option);
|
||||
|
||||
void _profiler_activate(bool p_enable, int p_profiler);
|
||||
void _profiler_seeked();
|
||||
|
|
@ -385,6 +395,8 @@ public:
|
|||
void send_message(const String &p_message, const Array &p_args);
|
||||
void toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data);
|
||||
|
||||
void update_layout(EditorDock::DockLayout p_layout, int p_slot);
|
||||
|
||||
ScriptEditorDebugger();
|
||||
~ScriptEditorDebugger();
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue