editor_debugger_plugin.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #include "editor_debugger_plugin.h"
  31. #include "editor/debugger/script_editor_debugger.h"
  32. void EditorDebuggerSession::_breaked(bool p_really_did, bool p_can_debug, const String &p_message, bool p_has_stackdump) {
  33. if (p_really_did) {
  34. emit_signal(SNAME("breaked"), p_can_debug);
  35. } else {
  36. emit_signal(SNAME("continued"));
  37. }
  38. }
  39. void EditorDebuggerSession::_started() {
  40. emit_signal(SNAME("started"));
  41. }
  42. void EditorDebuggerSession::_stopped() {
  43. emit_signal(SNAME("stopped"));
  44. }
  45. void EditorDebuggerSession::_bind_methods() {
  46. ClassDB::bind_method(D_METHOD("send_message", "message", "data"), &EditorDebuggerSession::send_message, DEFVAL(Array()));
  47. ClassDB::bind_method(D_METHOD("toggle_profiler", "profiler", "enable", "data"), &EditorDebuggerSession::toggle_profiler, DEFVAL(Array()));
  48. ClassDB::bind_method(D_METHOD("is_breaked"), &EditorDebuggerSession::is_breaked);
  49. ClassDB::bind_method(D_METHOD("is_debuggable"), &EditorDebuggerSession::is_debuggable);
  50. ClassDB::bind_method(D_METHOD("is_active"), &EditorDebuggerSession::is_active);
  51. ClassDB::bind_method(D_METHOD("add_session_tab", "control"), &EditorDebuggerSession::add_session_tab);
  52. ClassDB::bind_method(D_METHOD("remove_session_tab", "control"), &EditorDebuggerSession::remove_session_tab);
  53. ClassDB::bind_method(D_METHOD("set_breakpoint", "path", "line", "enabled"), &EditorDebuggerSession::set_breakpoint);
  54. ADD_SIGNAL(MethodInfo("started"));
  55. ADD_SIGNAL(MethodInfo("stopped"));
  56. ADD_SIGNAL(MethodInfo("breaked", PropertyInfo(Variant::BOOL, "can_debug")));
  57. ADD_SIGNAL(MethodInfo("continued"));
  58. }
  59. void EditorDebuggerSession::add_session_tab(Control *p_tab) {
  60. ERR_FAIL_COND(!p_tab || !debugger);
  61. debugger->add_debugger_tab(p_tab);
  62. tabs.insert(p_tab);
  63. }
  64. void EditorDebuggerSession::remove_session_tab(Control *p_tab) {
  65. ERR_FAIL_COND(!p_tab || !debugger);
  66. debugger->remove_debugger_tab(p_tab);
  67. tabs.erase(p_tab);
  68. }
  69. void EditorDebuggerSession::send_message(const String &p_message, const Array &p_args) {
  70. ERR_FAIL_NULL_MSG(debugger, "Plugin is not attached to debugger.");
  71. debugger->send_message(p_message, p_args);
  72. }
  73. void EditorDebuggerSession::toggle_profiler(const String &p_profiler, bool p_enable, const Array &p_data) {
  74. ERR_FAIL_NULL_MSG(debugger, "Plugin is not attached to debugger.");
  75. debugger->toggle_profiler(p_profiler, p_enable, p_data);
  76. }
  77. bool EditorDebuggerSession::is_breaked() {
  78. ERR_FAIL_NULL_V_MSG(debugger, false, "Plugin is not attached to debugger.");
  79. return debugger->is_breaked();
  80. }
  81. bool EditorDebuggerSession::is_debuggable() {
  82. ERR_FAIL_NULL_V_MSG(debugger, false, "Plugin is not attached to debugger.");
  83. return debugger->is_debuggable();
  84. }
  85. bool EditorDebuggerSession::is_active() {
  86. ERR_FAIL_NULL_V_MSG(debugger, false, "Plugin is not attached to debugger.");
  87. return debugger->is_session_active();
  88. }
  89. void EditorDebuggerSession::set_breakpoint(const String &p_path, int p_line, bool p_enabled) {
  90. ERR_FAIL_NULL_MSG(debugger, "Plugin is not attached to debugger.");
  91. debugger->set_breakpoint(p_path, p_line, p_enabled);
  92. }
  93. void EditorDebuggerSession::detach_debugger() {
  94. if (!debugger) {
  95. return;
  96. }
  97. debugger->disconnect("started", callable_mp(this, &EditorDebuggerSession::_started));
  98. debugger->disconnect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
  99. debugger->disconnect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
  100. debugger->disconnect(SceneStringName(tree_exited), callable_mp(this, &EditorDebuggerSession::_debugger_gone_away));
  101. for (Control *tab : tabs) {
  102. debugger->remove_debugger_tab(tab);
  103. }
  104. tabs.clear();
  105. debugger = nullptr;
  106. }
  107. void EditorDebuggerSession::_debugger_gone_away() {
  108. debugger = nullptr;
  109. tabs.clear();
  110. }
  111. EditorDebuggerSession::EditorDebuggerSession(ScriptEditorDebugger *p_debugger) {
  112. ERR_FAIL_NULL(p_debugger);
  113. debugger = p_debugger;
  114. debugger->connect("started", callable_mp(this, &EditorDebuggerSession::_started));
  115. debugger->connect("stopped", callable_mp(this, &EditorDebuggerSession::_stopped));
  116. debugger->connect("breaked", callable_mp(this, &EditorDebuggerSession::_breaked));
  117. debugger->connect(SceneStringName(tree_exited), callable_mp(this, &EditorDebuggerSession::_debugger_gone_away), CONNECT_ONE_SHOT);
  118. }
  119. EditorDebuggerSession::~EditorDebuggerSession() {
  120. detach_debugger();
  121. }
  122. /// EditorDebuggerPlugin
  123. EditorDebuggerPlugin::~EditorDebuggerPlugin() {
  124. clear();
  125. }
  126. void EditorDebuggerPlugin::clear() {
  127. for (Ref<EditorDebuggerSession> &session : sessions) {
  128. session->detach_debugger();
  129. }
  130. sessions.clear();
  131. }
  132. void EditorDebuggerPlugin::create_session(ScriptEditorDebugger *p_debugger) {
  133. sessions.push_back(Ref<EditorDebuggerSession>(memnew(EditorDebuggerSession(p_debugger))));
  134. setup_session(sessions.size() - 1);
  135. }
  136. void EditorDebuggerPlugin::setup_session(int p_idx) {
  137. GDVIRTUAL_CALL(_setup_session, p_idx);
  138. }
  139. Ref<EditorDebuggerSession> EditorDebuggerPlugin::get_session(int p_idx) {
  140. ERR_FAIL_INDEX_V(p_idx, sessions.size(), nullptr);
  141. return sessions.get(p_idx);
  142. }
  143. Array EditorDebuggerPlugin::get_sessions() {
  144. Array ret;
  145. for (const Ref<EditorDebuggerSession> &session : sessions) {
  146. ret.push_back(session);
  147. }
  148. return ret;
  149. }
  150. bool EditorDebuggerPlugin::has_capture(const String &p_message) const {
  151. bool ret = false;
  152. if (GDVIRTUAL_CALL(_has_capture, p_message, ret)) {
  153. return ret;
  154. }
  155. return false;
  156. }
  157. bool EditorDebuggerPlugin::capture(const String &p_message, const Array &p_data, int p_session_id) {
  158. bool ret = false;
  159. if (GDVIRTUAL_CALL(_capture, p_message, p_data, p_session_id, ret)) {
  160. return ret;
  161. }
  162. return false;
  163. }
  164. void EditorDebuggerPlugin::goto_script_line(const Ref<Script> &p_script, int p_line) {
  165. GDVIRTUAL_CALL(_goto_script_line, p_script, p_line);
  166. }
  167. void EditorDebuggerPlugin::breakpoints_cleared_in_tree() {
  168. GDVIRTUAL_CALL(_breakpoints_cleared_in_tree);
  169. }
  170. void EditorDebuggerPlugin::breakpoint_set_in_tree(const Ref<Script> &p_script, int p_line, bool p_enabled) {
  171. GDVIRTUAL_CALL(_breakpoint_set_in_tree, p_script, p_line, p_enabled);
  172. }
  173. void EditorDebuggerPlugin::_bind_methods() {
  174. GDVIRTUAL_BIND(_setup_session, "session_id");
  175. GDVIRTUAL_BIND(_has_capture, "capture");
  176. GDVIRTUAL_BIND(_capture, "message", "data", "session_id");
  177. GDVIRTUAL_BIND(_goto_script_line, "script", "line");
  178. GDVIRTUAL_BIND(_breakpoints_cleared_in_tree);
  179. GDVIRTUAL_BIND(_breakpoint_set_in_tree, "script", "line", "enabled");
  180. ClassDB::bind_method(D_METHOD("get_session", "id"), &EditorDebuggerPlugin::get_session);
  181. ClassDB::bind_method(D_METHOD("get_sessions"), &EditorDebuggerPlugin::get_sessions);
  182. }
  183. EditorDebuggerPlugin::EditorDebuggerPlugin() {
  184. EditorDebuggerNode::get_singleton()->connect("goto_script_line", callable_mp(this, &EditorDebuggerPlugin::goto_script_line));
  185. EditorDebuggerNode::get_singleton()->connect("breakpoints_cleared_in_tree", callable_mp(this, &EditorDebuggerPlugin::breakpoints_cleared_in_tree));
  186. EditorDebuggerNode::get_singleton()->connect("breakpoint_set_in_tree", callable_mp(this, &EditorDebuggerPlugin::breakpoint_set_in_tree));
  187. }