Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/debugger/editor_debugger_plugin.cpp
9902 views
1
/**************************************************************************/
2
/* editor_debugger_plugin.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "editor_debugger_plugin.h"
32
33
#include "editor/debugger/script_editor_debugger.h"
34
35
void EditorDebuggerSession::_breaked(bool p_really_did, bool p_can_debug, const String &p_message, bool p_has_stackdump) {
36
if (p_really_did) {
37
emit_signal(SNAME("breaked"), p_can_debug);
38
} else {
39
emit_signal(SNAME("continued"));
40
}
41
}
42
43
void EditorDebuggerSession::_started() {
44
emit_signal(SNAME("started"));
45
}
46
47
void EditorDebuggerSession::_stopped() {
48
emit_signal(SNAME("stopped"));
49
}
50
51
void EditorDebuggerSession::_bind_methods() {
52
ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerSession::send_message, DEFVAL(Array()));
53
ClassDB::bind_method(D_METHOD("toggle_profiler", "profiler", "enable", "data"), &EditorDebuggerSession::toggle_profiler, DEFVAL(Array()));
54
ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerSession::is_breaked);
55
ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerSession::is_debuggable);
56
ClassDB::bind_method(D_METHOD("is_active"), &EditorDebuggerSession::is_active);
57
ClassDB::bind_method(D_METHOD("add_session_tab", "control"), &EditorDebuggerSession::add_session_tab);
58
ClassDB::bind_method(D_METHOD("remove_session_tab", "control"), &EditorDebuggerSession::remove_session_tab);
59
ClassDB::bind_method(D_METHOD("set_breakpoint", "path", "line", "enabled"), &EditorDebuggerSession::set_breakpoint);
60
61
ADD_SIGNAL(MethodInfo("started"));
62
ADD_SIGNAL(MethodInfo("stopped"));
63
ADD_SIGNAL(MethodInfo("breaked", PropertyInfo(Variant::BOOL, "can_debug")));
64
ADD_SIGNAL(MethodInfo("continued"));
65
}
66
67
void EditorDebuggerSession::add_session_tab(Control *p_tab) {
68
ERR_FAIL_COND(!p_tab || !debugger);
69
debugger->add_debugger_tab(p_tab);
70
tabs.insert(p_tab);
71
}
72
73
void EditorDebuggerSession::remove_session_tab(Control *p_tab) {
74
ERR_FAIL_COND(!p_tab || !debugger);
75
debugger->remove_debugger_tab(p_tab);
76
tabs.erase(p_tab);
77
}
78
79
void EditorDebuggerSession::send_message(const String &p_message, const Array &p_args) {
80
ERR_FAIL_NULL_MSG(debugger, "Plugin is not attached to debugger.");
81
debugger->send_message(p_message, p_args);
82
}
83
84
void EditorDebuggerSession::toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data) {
85
ERR_FAIL_NULL_MSG(debugger, "Plugin is not attached to debugger.");
86
debugger->toggle_profiler(p_profiler, p_enable, p_data);
87
}
88
89
bool EditorDebuggerSession::is_breaked() {
90
ERR_FAIL_NULL_V_MSG(debugger, false, "Plugin is not attached to debugger.");
91
return debugger->is_breaked();
92
}
93
94
bool EditorDebuggerSession::is_debuggable() {
95
ERR_FAIL_NULL_V_MSG(debugger, false, "Plugin is not attached to debugger.");
96
return debugger->is_debuggable();
97
}
98
99
bool EditorDebuggerSession::is_active() {
100
ERR_FAIL_NULL_V_MSG(debugger, false, "Plugin is not attached to debugger.");
101
return debugger->is_session_active();
102
}
103
104
void EditorDebuggerSession::set_breakpoint(const String &p_path, int p_line, bool p_enabled) {
105
ERR_FAIL_NULL_MSG(debugger, "Plugin is not attached to debugger.");
106
debugger->set_breakpoint(p_path, p_line, p_enabled);
107
}
108
109
void EditorDebuggerSession::detach_debugger() {
110
if (!debugger) {
111
return;
112
}
113
debugger->disconnect("started", callable_mp(this, &EditorDebuggerSession::_started));
114
debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
115
debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
116
debugger->disconnect(SceneStringName(tree_exited), callable_mp(this, &EditorDebuggerSession::_debugger_gone_away));
117
for (Control *tab : tabs) {
118
debugger->remove_debugger_tab(tab);
119
}
120
tabs.clear();
121
debugger = nullptr;
122
}
123
124
void EditorDebuggerSession::_debugger_gone_away() {
125
debugger = nullptr;
126
tabs.clear();
127
}
128
129
EditorDebuggerSession::EditorDebuggerSession(ScriptEditorDebugger *p_debugger) {
130
ERR_FAIL_NULL(p_debugger);
131
debugger = p_debugger;
132
debugger->connect("started", callable_mp(this, &EditorDebuggerSession::_started));
133
debugger->connect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
134
debugger->connect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
135
debugger->connect(SceneStringName(tree_exited), callable_mp(this, &EditorDebuggerSession::_debugger_gone_away), CONNECT_ONE_SHOT);
136
}
137
138
EditorDebuggerSession::~EditorDebuggerSession() {
139
detach_debugger();
140
}
141
142
/// EditorDebuggerPlugin
143
144
EditorDebuggerPlugin::~EditorDebuggerPlugin() {
145
clear();
146
}
147
148
void EditorDebuggerPlugin::clear() {
149
for (Ref<EditorDebuggerSession> &session : sessions) {
150
session->detach_debugger();
151
}
152
sessions.clear();
153
}
154
155
void EditorDebuggerPlugin::create_session(ScriptEditorDebugger *p_debugger) {
156
sessions.push_back(Ref<EditorDebuggerSession>(memnew(EditorDebuggerSession(p_debugger))));
157
setup_session(sessions.size() - 1);
158
}
159
160
void EditorDebuggerPlugin::setup_session(int p_idx) {
161
GDVIRTUAL_CALL(_setup_session, p_idx);
162
}
163
164
Ref<EditorDebuggerSession> EditorDebuggerPlugin::get_session(int p_idx) {
165
ERR_FAIL_INDEX_V(p_idx, sessions.size(), nullptr);
166
return sessions.get(p_idx);
167
}
168
169
Array EditorDebuggerPlugin::get_sessions() {
170
Array ret;
171
for (const Ref<EditorDebuggerSession> &session : sessions) {
172
ret.push_back(session);
173
}
174
return ret;
175
}
176
177
bool EditorDebuggerPlugin::has_capture(const String &p_message) const {
178
bool ret = false;
179
if (GDVIRTUAL_CALL(_has_capture, p_message, ret)) {
180
return ret;
181
}
182
return false;
183
}
184
185
bool EditorDebuggerPlugin::capture(const String &p_message, const Array &p_data, int p_session_id) {
186
bool ret = false;
187
if (GDVIRTUAL_CALL(_capture, p_message, p_data, p_session_id, ret)) {
188
return ret;
189
}
190
return false;
191
}
192
193
void EditorDebuggerPlugin::goto_script_line(const Ref<Script> &p_script, int p_line) {
194
GDVIRTUAL_CALL(_goto_script_line, p_script, p_line);
195
}
196
197
void EditorDebuggerPlugin::breakpoints_cleared_in_tree() {
198
GDVIRTUAL_CALL(_breakpoints_cleared_in_tree);
199
}
200
201
void EditorDebuggerPlugin::breakpoint_set_in_tree(const Ref<Script> &p_script, int p_line, bool p_enabled) {
202
GDVIRTUAL_CALL(_breakpoint_set_in_tree, p_script, p_line, p_enabled);
203
}
204
205
void EditorDebuggerPlugin::_bind_methods() {
206
GDVIRTUAL_BIND(_setup_session, "session_id");
207
GDVIRTUAL_BIND(_has_capture, "capture");
208
GDVIRTUAL_BIND(_capture, "message", "data", "session_id");
209
GDVIRTUAL_BIND(_goto_script_line, "script", "line");
210
GDVIRTUAL_BIND(_breakpoints_cleared_in_tree);
211
GDVIRTUAL_BIND(_breakpoint_set_in_tree, "script", "line", "enabled");
212
ClassDB::bind_method(D_METHOD("get_session", "id"), &EditorDebuggerPlugin::get_session);
213
ClassDB::bind_method(D_METHOD("get_sessions"), &EditorDebuggerPlugin::get_sessions);
214
}
215
216
EditorDebuggerPlugin::EditorDebuggerPlugin() {
217
EditorDebuggerNode::get_singleton()->connect("goto_script_line", callable_mp(this, &EditorDebuggerPlugin::goto_script_line));
218
EditorDebuggerNode::get_singleton()->connect("breakpoints_cleared_in_tree", callable_mp(this, &EditorDebuggerPlugin::breakpoints_cleared_in_tree));
219
EditorDebuggerNode::get_singleton()->connect("breakpoint_set_in_tree", callable_mp(this, &EditorDebuggerPlugin::breakpoint_set_in_tree));
220
}
221
222