[Editor] Better expose EditorDebuggerPlugin.

Now splitted into two classes:
- EditorDebuggerPlugin (RefCounted).
- EditorDebuggerSession (abstract).

This allows the EditorPlugin to be in control of the debugger plugin
lifecycle, be notified when sessions are created, and customize each of
them independently.

We should slowly transition the various profilers and captures in
ScriptEditorDebugger to their own plugins, and decouple
ScriptEditorDebugger from it's UI part (making it the "real"
EditorDebuggerSession potentially dropping the wrappers).
This commit is contained in:
Fabio Alessandrelli 2022-10-03 15:21:25 +02:00
parent 471c42ee1f
commit d568b25e36
12 changed files with 371 additions and 202 deletions

View file

@ -32,7 +32,7 @@
#include "editor/debugger/script_editor_debugger.h"
void EditorDebuggerPlugin::_breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump) {
void EditorDebuggerSession::_breaked(bool p_really_did, bool p_can_debug, String p_message, bool p_has_stackdump) {
if (p_really_did) {
emit_signal(SNAME("breaked"), p_can_debug);
} else {
@ -40,22 +40,22 @@ void EditorDebuggerPlugin::_breaked(bool p_really_did, bool p_can_debug, String
}
}
void EditorDebuggerPlugin::_started() {
void EditorDebuggerSession::_started() {
emit_signal(SNAME("started"));
}
void EditorDebuggerPlugin::_stopped() {
void EditorDebuggerSession::_stopped() {
emit_signal(SNAME("stopped"));
}
void EditorDebuggerPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerPlugin::send_message);
ClassDB::bind_method(D_METHOD("register_message_capture", "name", "callable"), &EditorDebuggerPlugin::register_message_capture);
ClassDB::bind_method(D_METHOD("unregister_message_capture", "name"), &EditorDebuggerPlugin::unregister_message_capture);
ClassDB::bind_method(D_METHOD("has_capture", "name"), &EditorDebuggerPlugin::has_capture);
ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerPlugin::is_breaked);
ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerPlugin::is_debuggable);
ClassDB::bind_method(D_METHOD("is_session_active"), &EditorDebuggerPlugin::is_session_active);
void EditorDebuggerSession::_bind_methods() {
ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerSession::send_message, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("toggle_profiler", "profiler", "enable", "data"), &EditorDebuggerSession::toggle_profiler, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerSession::is_breaked);
ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerSession::is_debuggable);
ClassDB::bind_method(D_METHOD("is_active"), &EditorDebuggerSession::is_active);
ClassDB::bind_method(D_METHOD("add_session_tab", "control"), &EditorDebuggerSession::add_session_tab);
ClassDB::bind_method(D_METHOD("remove_session_tab", "control"), &EditorDebuggerSession::remove_session_tab);
ADD_SIGNAL(MethodInfo("started"));
ADD_SIGNAL(MethodInfo("stopped"));
@ -63,62 +63,131 @@ void EditorDebuggerPlugin::_bind_methods() {
ADD_SIGNAL(MethodInfo("continued"));
}
void EditorDebuggerPlugin::attach_debugger(ScriptEditorDebugger *p_debugger) {
debugger = p_debugger;
if (debugger) {
debugger->connect("started", callable_mp(this, &EditorDebuggerPlugin::_started));
debugger->connect("stopped", callable_mp(this, &EditorDebuggerPlugin::_stopped));
debugger->connect("breaked", callable_mp(this, &EditorDebuggerPlugin::_breaked));
}
void EditorDebuggerSession::add_session_tab(Control *p_tab) {
ERR_FAIL_COND(!p_tab || !debugger);
debugger->add_debugger_tab(p_tab);
tabs.insert(p_tab);
}
void EditorDebuggerPlugin::detach_debugger(bool p_call_debugger) {
if (debugger) {
debugger->disconnect("started", callable_mp(this, &EditorDebuggerPlugin::_started));
debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerPlugin::_stopped));
debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerPlugin::_breaked));
if (p_call_debugger && get_script_instance()) {
debugger->remove_debugger_plugin(get_script_instance()->get_script());
}
debugger = nullptr;
}
void EditorDebuggerSession::remove_session_tab(Control *p_tab) {
ERR_FAIL_COND(!p_tab || !debugger);
debugger->remove_debugger_tab(p_tab);
tabs.erase(p_tab);
}
void EditorDebuggerPlugin::send_message(const String &p_message, const Array &p_args) {
void EditorDebuggerSession::send_message(const String &p_message, const Array &p_args) {
ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger");
debugger->send_message(p_message, p_args);
}
void EditorDebuggerPlugin::register_message_capture(const StringName &p_name, const Callable &p_callable) {
void EditorDebuggerSession::toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data) {
ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger");
debugger->register_message_capture(p_name, p_callable);
debugger->toggle_profiler(p_profiler, p_enable, p_data);
}
void EditorDebuggerPlugin::unregister_message_capture(const StringName &p_name) {
ERR_FAIL_COND_MSG(!debugger, "Plugin is not attached to debugger");
debugger->unregister_message_capture(p_name);
}
bool EditorDebuggerPlugin::has_capture(const StringName &p_name) {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->has_capture(p_name);
}
bool EditorDebuggerPlugin::is_breaked() {
bool EditorDebuggerSession::is_breaked() {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->is_breaked();
}
bool EditorDebuggerPlugin::is_debuggable() {
bool EditorDebuggerSession::is_debuggable() {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->is_debuggable();
}
bool EditorDebuggerPlugin::is_session_active() {
bool EditorDebuggerSession::is_active() {
ERR_FAIL_COND_V_MSG(!debugger, false, "Plugin is not attached to debugger");
return debugger->is_session_active();
}
EditorDebuggerPlugin::~EditorDebuggerPlugin() {
detach_debugger(true);
void EditorDebuggerSession::detach_debugger() {
if (!debugger) {
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("tree_exited", callable_mp(this, &EditorDebuggerSession::_debugger_gone_away));
for (Control *tab : tabs) {
debugger->remove_debugger_tab(tab);
}
tabs.clear();
debugger = nullptr;
}
void EditorDebuggerSession::_debugger_gone_away() {
debugger = nullptr;
tabs.clear();
}
EditorDebuggerSession::EditorDebuggerSession(ScriptEditorDebugger *p_debugger) {
ERR_FAIL_COND(!p_debugger);
debugger = p_debugger;
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("tree_exited", callable_mp(this, &EditorDebuggerSession::_debugger_gone_away), CONNECT_ONE_SHOT);
}
EditorDebuggerSession::~EditorDebuggerSession() {
detach_debugger();
}
/// EditorDebuggerPlugin
EditorDebuggerPlugin::~EditorDebuggerPlugin() {
clear();
}
void EditorDebuggerPlugin::clear() {
for (int i = 0; i < sessions.size(); i++) {
sessions[i]->detach_debugger();
}
sessions.clear();
}
void EditorDebuggerPlugin::create_session(ScriptEditorDebugger *p_debugger) {
sessions.push_back(Ref<EditorDebuggerSession>(memnew(EditorDebuggerSession(p_debugger))));
setup_session(sessions.size() - 1);
}
void EditorDebuggerPlugin::setup_session(int p_idx) {
GDVIRTUAL_CALL(_setup_session, p_idx);
}
Ref<EditorDebuggerSession> EditorDebuggerPlugin::get_session(int p_idx) {
ERR_FAIL_INDEX_V(p_idx, sessions.size(), nullptr);
return sessions[p_idx];
}
Array EditorDebuggerPlugin::get_sessions() {
Array ret;
for (int i = 0; i < sessions.size(); i++) {
ret.push_back(sessions[i]);
}
return ret;
}
bool EditorDebuggerPlugin::has_capture(const String &p_message) const {
bool ret = false;
if (GDVIRTUAL_CALL(_has_capture, p_message, ret)) {
return ret;
}
return false;
}
bool EditorDebuggerPlugin::capture(const String &p_message, const Array &p_data, int p_session_id) {
bool ret = false;
if (GDVIRTUAL_CALL(_capture, p_message, p_data, p_session_id, ret)) {
return ret;
}
return false;
}
void EditorDebuggerPlugin::_bind_methods() {
GDVIRTUAL_BIND(_setup_session, "session_id");
GDVIRTUAL_BIND(_has_capture, "capture");
GDVIRTUAL_BIND(_capture, "message", "data", "session_id");
ClassDB::bind_method(D_METHOD("get_session", "id"), &EditorDebuggerPlugin::get_session);
ClassDB::bind_method(D_METHOD("get_sessions"), &EditorDebuggerPlugin::get_sessions);
}