Added debugger plugin support
Changes: * EngineDebugger is exposed to gdscript. Game side of communication can be implemented through it. * EditorDebuggerPlugin is added which handles the editor side of communication.
This commit is contained in:
parent
a609b30ddb
commit
ea2eaf8c27
16 changed files with 780 additions and 1 deletions
|
|
@ -34,6 +34,7 @@
|
|||
#include "editor/debugger/script_editor_debugger.h"
|
||||
#include "editor/editor_log.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/plugins/editor_debugger_plugin.h"
|
||||
#include "editor/plugins/script_editor_plugin.h"
|
||||
#include "scene/gui/menu_button.h"
|
||||
#include "scene/gui/tab_container.h"
|
||||
|
|
@ -114,6 +115,12 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() {
|
|||
tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles"));
|
||||
}
|
||||
|
||||
if (!debugger_plugins.empty()) {
|
||||
for (Set<Ref<Script>>::Element *i = debugger_plugins.front(); i; i = i->next()) {
|
||||
node->add_debugger_plugin(i->get());
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
@ -618,3 +625,23 @@ void EditorDebuggerNode::live_debug_reparent_node(const NodePath &p_at, const No
|
|||
dbg->live_debug_reparent_node(p_at, p_new_place, p_new_name, p_at_pos);
|
||||
});
|
||||
}
|
||||
|
||||
void EditorDebuggerNode::add_debugger_plugin(const Ref<Script> &p_script) {
|
||||
ERR_FAIL_COND_MSG(debugger_plugins.has(p_script), "Debugger plugin already exists.");
|
||||
ERR_FAIL_COND_MSG(p_script.is_null(), "Debugger plugin script is null");
|
||||
ERR_FAIL_COND_MSG(String(p_script->get_instance_base_type()) == "", "Debugger plugin script has error.");
|
||||
ERR_FAIL_COND_MSG(String(p_script->get_instance_base_type()) != "EditorDebuggerPlugin", "Base type of debugger plugin is not 'EditorDebuggerPlugin'.");
|
||||
ERR_FAIL_COND_MSG(!p_script->is_tool(), "Debugger plugin script is not in tool mode.");
|
||||
debugger_plugins.insert(p_script);
|
||||
for (int i = 0; get_debugger(i); i++) {
|
||||
get_debugger(i)->add_debugger_plugin(p_script);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorDebuggerNode::remove_debugger_plugin(const Ref<Script> &p_script) {
|
||||
ERR_FAIL_COND_MSG(!debugger_plugins.has(p_script), "Debugger plugin doesn't exists.");
|
||||
debugger_plugins.erase(p_script);
|
||||
for (int i = 0; get_debugger(i); i++) {
|
||||
get_debugger(i)->remove_debugger_plugin(p_script);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ private:
|
|||
CameraOverride camera_override = OVERRIDE_NONE;
|
||||
Map<Breakpoint, bool> breakpoints;
|
||||
|
||||
Set<Ref<Script>> debugger_plugins;
|
||||
|
||||
ScriptEditorDebugger *_add_debugger();
|
||||
EditorDebuggerRemoteObject *get_inspected_remote_object();
|
||||
|
||||
|
|
@ -186,5 +188,8 @@ public:
|
|||
Error start(const String &p_protocol = "tcp://");
|
||||
|
||||
void stop();
|
||||
|
||||
void add_debugger_plugin(const Ref<Script> &p_script);
|
||||
void remove_debugger_plugin(const Ref<Script> &p_script);
|
||||
};
|
||||
#endif // EDITOR_DEBUGGER_NODE_H
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "editor/editor_scale.h"
|
||||
#include "editor/editor_settings.h"
|
||||
#include "editor/plugins/canvas_item_editor_plugin.h"
|
||||
#include "editor/plugins/editor_debugger_plugin.h"
|
||||
#include "editor/plugins/node_3d_editor_plugin.h"
|
||||
#include "editor/property_editor.h"
|
||||
#include "main/performance.h"
|
||||
|
|
@ -701,7 +702,28 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
|
|||
performance_profiler->update_monitors(monitors);
|
||||
|
||||
} else {
|
||||
WARN_PRINT("unknown message " + p_msg);
|
||||
int colon_index = p_msg.find_char(':');
|
||||
ERR_FAIL_COND_MSG(colon_index < 1, "Invalid message received");
|
||||
|
||||
bool parsed = false;
|
||||
const String cap = p_msg.substr(0, colon_index);
|
||||
Map<StringName, Callable>::Element *element = captures.find(cap);
|
||||
if (element) {
|
||||
Callable &c = element->value();
|
||||
ERR_FAIL_COND_MSG(c.is_null(), "Invalid callable registered: " + cap);
|
||||
Variant cmd = p_msg.substr(colon_index + 1), data = p_data;
|
||||
const Variant *args[2] = { &cmd, &data };
|
||||
Variant retval;
|
||||
Callable::CallError err;
|
||||
c.call(args, 2, retval, err);
|
||||
ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'capture' to callable: " + Variant::get_callable_error_text(c, args, 2, err));
|
||||
ERR_FAIL_COND_MSG(retval.get_type() != Variant::BOOL, "Error calling 'capture' to callable: " + String(c) + ". Return type is not bool.");
|
||||
parsed = retval;
|
||||
}
|
||||
|
||||
if (!parsed) {
|
||||
WARN_PRINT("unknown message " + p_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -847,6 +869,7 @@ void ScriptEditorDebugger::start(Ref<RemoteDebuggerPeer> p_peer) {
|
|||
tabs->set_current_tab(0);
|
||||
_set_reason_text(TTR("Debug session started."), MESSAGE_SUCCESS);
|
||||
_update_buttons_state();
|
||||
emit_signal("started");
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::_update_buttons_state() {
|
||||
|
|
@ -1395,6 +1418,7 @@ void ScriptEditorDebugger::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("request_remote_object", "id"), &ScriptEditorDebugger::request_remote_object);
|
||||
ClassDB::bind_method(D_METHOD("update_remote_object", "id", "property", "value"), &ScriptEditorDebugger::update_remote_object);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("started"));
|
||||
ADD_SIGNAL(MethodInfo("stopped"));
|
||||
ADD_SIGNAL(MethodInfo("stop_requested"));
|
||||
ADD_SIGNAL(MethodInfo("stack_frame_selected", PropertyInfo(Variant::INT, "frame")));
|
||||
|
|
@ -1408,6 +1432,43 @@ void ScriptEditorDebugger::_bind_methods() {
|
|||
ADD_SIGNAL(MethodInfo("remote_tree_updated"));
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::add_debugger_plugin(const Ref<Script> &p_script) {
|
||||
if (!debugger_plugins.has(p_script)) {
|
||||
EditorDebuggerPlugin *plugin = memnew(EditorDebuggerPlugin());
|
||||
plugin->attach_debugger(this);
|
||||
plugin->set_script(p_script);
|
||||
tabs->add_child(plugin);
|
||||
debugger_plugins.insert(p_script, plugin);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::remove_debugger_plugin(const Ref<Script> &p_script) {
|
||||
if (debugger_plugins.has(p_script)) {
|
||||
tabs->remove_child(debugger_plugins[p_script]);
|
||||
debugger_plugins[p_script]->detach_debugger(false);
|
||||
memdelete(debugger_plugins[p_script]);
|
||||
debugger_plugins.erase(p_script);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::send_message(const String &p_message, const Array &p_args) {
|
||||
_put_msg(p_message, p_args);
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::register_message_capture(const StringName &p_name, const Callable &p_callable) {
|
||||
ERR_FAIL_COND_MSG(has_capture(p_name), "Capture already registered: " + p_name);
|
||||
captures.insert(p_name, p_callable);
|
||||
}
|
||||
|
||||
void ScriptEditorDebugger::unregister_message_capture(const StringName &p_name) {
|
||||
ERR_FAIL_COND_MSG(!has_capture(p_name), "Capture not registered: " + p_name);
|
||||
captures.erase(p_name);
|
||||
}
|
||||
|
||||
bool ScriptEditorDebugger::has_capture(const StringName &p_name) {
|
||||
return captures.has(p_name);
|
||||
}
|
||||
|
||||
ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
|
||||
editor = p_editor;
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ class EditorVisualProfiler;
|
|||
class EditorNetworkProfiler;
|
||||
class EditorPerformanceProfiler;
|
||||
class SceneDebuggerTree;
|
||||
class EditorDebuggerPlugin;
|
||||
|
||||
class ScriptEditorDebugger : public MarginContainer {
|
||||
GDCLASS(ScriptEditorDebugger, MarginContainer);
|
||||
|
|
@ -146,6 +147,10 @@ private:
|
|||
|
||||
EditorDebuggerNode::CameraOverride camera_override;
|
||||
|
||||
Map<Ref<Script>, EditorDebuggerPlugin *> debugger_plugins;
|
||||
|
||||
Map<StringName, Callable> captures;
|
||||
|
||||
void _stack_dump_frame_selected();
|
||||
|
||||
void _file_selected(const String &p_file);
|
||||
|
|
@ -253,6 +258,16 @@ public:
|
|||
bool is_skip_breakpoints();
|
||||
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
|
||||
void add_debugger_plugin(const Ref<Script> &p_script);
|
||||
void remove_debugger_plugin(const Ref<Script> &p_script);
|
||||
|
||||
void send_message(const String &p_message, const Array &p_args);
|
||||
|
||||
void register_message_capture(const StringName &p_name, const Callable &p_callable);
|
||||
void unregister_message_capture(const StringName &p_name);
|
||||
bool has_capture(const StringName &p_name);
|
||||
|
||||
ScriptEditorDebugger(EditorNode *p_editor = nullptr);
|
||||
~ScriptEditorDebugger();
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue