feat: updated engine

This commit is contained in:
Sara Gerretsen 2026-07-10 17:04:34 +02:00
parent cbe99774ff
commit f4cf6b3999
6607 changed files with 910135 additions and 430025 deletions

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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() {

View file

@ -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"

View file

@ -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();

View file

@ -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);
}

View file

@ -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(); }
};

View file

@ -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);

View file

@ -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);

View file

@ -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() {

View file

@ -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();

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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"

View file

@ -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;

View file

@ -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));

View file

@ -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);

View file

@ -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));

View file

@ -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();

View file

@ -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();
}

View file

@ -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();
};